views:

157

answers:

10
class A {

public void talk(){
 this.sayIt();
}

private void sayIt(){
 System.out.println("class A says...");
}


}

class B extends A {

private void sayIt(){
 System.out.println("class B says...");
}


}


B b = new B();
b.talk() 
//output
class A says...

I cannot get this since:

Class B inherits from class A the public member and cannot see/inherit the private function.

So in class B we could call talk() //since it is inherited by the parent class.

Now in the talk() method there is a call to sayIt() and since say it is defined in class B i would expect a call to B.sayIt() to be made when this.sayIt() is executed.

Doesn't "this" refer to the B class ?

If you have some time please explain..

+3  A: 

Consider making protected instead of private on sayIt. sayIt on B is not overriding sayIt on A.

John Paulett
Thanks, but how does the A.sayIt() gets called since it is not visible from B's context?
andreas
Since sayIt is private, the JVM knows that when talk calls sayIt, it does not need to look into any subclasses for overridden version of sayIt, so it makes the direct call the A.sayIt().
John Paulett
It isn't called from B, but from a method implemented in class A, which can see private methods in class A.
Mattias Nilsson
@andreas, A.sayIt() gets called because it is visible from A's context as A.talkIt() is in A context.
NawaMan
A: 

If you change the "sayIt" method to be protected it will work like you expect it to.

It seems like you're a little bit confused about how it works with overriding methods. If I'm not mistaken, what you are trying to do is perfectly alright in C++, but not in Java.

Mattias Nilsson
+2  A: 

You are trying to override private methods. It has no sense.

Sinuhe
A: 

Yes "this" of b.talkIt() refer to the B class but since sayIt() is private in A and talkIt() is decalred in A and not overridden in B, the sayIt() will be referred to the one in A.

You can look at it this way. sayIt() of A is private so it cannot be overridden. Since it is not overridden, sayIt() call by methods of A will always point to the one known to A (as it is not overridden).

Hope this helps.

NawaMan
A: 

"Doesn't "this" refer to the B class ?" - No. Though you create a the instance from class B you still refer the method of the base type which is talk(). One way you can achieve this same objective is thru template-method pattern.

/BB

Bumble Bee
A: 

Because sayIt is a private method, it is in fact not overridden. One way to help understand this is to add the @Override annotation to any method that you think overrides something from the superclass. If you are wrong (as in this case) then the compiler will tell you.

Yishai
A: 

Because in talk you reffer to this.sayIt and object B is instance of A.

Object A has no knowledge of methods in B. Make object A an abstract class with sayIt abstract method which you call in A talk or change visibility of sayIt.

Also - use annotaions and IDE will notify you with warnings.

Trick
A: 

According to Java language specification 8.4.8:

A class C inherits from its direct superclass and direct superinterfaces
all non-private methods (whether abstract or not) of the superclass and
superinterfaces that are public, protected or declared with default access
in the same package as C and are neither overridden nor hidden by a
declaration in the class.

So B did not inherit A.sayIt() and hence did not override it.

Murali VP
+5  A: 

Because you defined sayIt() to be private, class B cannot override it. As such, you have two definitions of sayIt() rather than just one that is overriden by a subclass.

While inside a section of class A code, it will always call the version from class A, even if the class B version was protected or public. This is because class A only knows about the version from class A since the class B version is not an override, but a completely different method that just so happens to share the same name.

While inside of a section of class B code, it will always call the version from class B since the class A version is marked private. As noted by others, if you change the definition to protected or public, it will be visible to class B and it will do what you want.

Note that if you were to use the default (package) visibility, the scoping rules would get to be very complex and the actual results would vary depending on which subclasses are in the same package and which are in different ones.

James
A: 

Slightly deviate from the topic but can help you to understand the Java inheritance better.

http://webmoli.com/2008/08/02/why-multiple-inheritance-is-not-allowed-in-java/

Venkat