I change your class and method names to real world equivalents to better understanding. I name a
as Animal
, testa
as Eat
, b
as Human
, and testb
as Talk
. So we have:
class Animal {
public void Eat() { }
}
class Human : Animal {
public void Talk() { }
}
Animal a1 = new Human();
Human b1 = new Animal();
OK, return to your questions.
1) You get error on second line, because every animal is NOT a human. Is it?
2) a1=new b()
according to our new naming conventions, turns to a1 = new Human
which means Animal a1 = new Human
. So, that's correct, because human is a kind of animal.
3) a1.testb()
according to our new naming conventions, turns to a1.Talk()
. Well, a1
is an animal (Animal a1
), and we can not expect an animal to talk.
MORE:
Think a class
is a group of attributes and behaviors. For example, we have a group named Animal
that defines an Eat
behavior. And another group named Human
that extends Animal
group and also it has its own behavior named Talk
. As we know, Human
has its super-group behaviors too -e.g. Eat
in this example-.
When we have an instance of group Animal
, we can expect it to eat. But we can not ask it to talk. It's not possible. In the other hand, every item that we choose from group Human
, is actually an Animal
. So we can ask him to eat.
When we have a Human
instance, we can ask him to behave as a Human
and as an Animal
too. I mean, we can ask him to Talk
and we can ask him to Eat
too. Every Human
can be located in human group, and in animal group.
1) When we say Human b1 = new Animal();
it says exactly: pick up an item from Animal
group - right part - and put it in Human
group - left part - which is not possible. Because there are a lot of animals which are not human.
2) When we say Animal a1 = new Human
: pick up an item from Human
group - right part - and put it in Animal
group - left part - which is easily possible.
3) When we say a1.Talk()
, we expect an Animal
to talk. I mean we expect an Animal
to act a Human
behavior which is not possible.