There are two things going on here.
First, keep in mind the distinction between the type of the reference and the type of the object.
When you say
A a = new B();
the reference is a
of type A
, but the object is of type B
. So when you call a.say(12);
, you are looking at B
from the A
API/interface/perspective.
Second, because you are looking at B
from the A
perspective, you are going to get an error because A
has no public method called say()
. Of course B
does, but remember you are treating B
as an A
. When you do that, you lose any ability (unless you cast later, but don't worry about that for now) to reference those B
methods that A
doesn't know about.
In the end, B
actually never inherits say()
from A
since it can't see it in the first place, and A
has no public method say()
for anyone to access.
Now if you want to really have some fun, make say()
protected in A
and private in B
and see what happens.