Pregunta

I have the a problem with the following four classes:

class X {
    void a() {
        b();
        c();
    }
    void b() {
        System.out.println("b from class X");
    }
    private void c() {
        System.out.println("c from class X");
    }
}

class Y extends X {    
    void b() {
        System.out.println("b from class Y");
    }
}

class Z extends Y {    
    void b() {
        System.out.println("b from class Z");
    }
    void c() {
        System.out.println("c from class Z");
    }    
}


public class Main {

    public static void main(String[] args) {
        Y y = new Z();
        y.a();
    }

}

Please don't comment reasonability of the classes, it's just an example. I also tried to follow the flow of the JVM through the methods using the eclipse debugger, but the steps throught the methods are at some points a bit to fast.

I already got, that

Y y = new Z();

creates the new instance of the Z class and assign it to a reference of the Y class. Since there is no constructor in Z, the compiler looks in each superclass whether there is an constructor, and in case there isn't one, it uses the constructor of the object class. After that the

y.a();

method is called. There is no such a method in class Z, so again we end up at class X where method a exists and execute it. First we execute method b which, because your object is an instance of class Z, and the method b is overwritten in class Z leads to the output

b from class Z.

After that the method c is called (in method a). Since our instance is still an instance from class Z and there exists a method c in this class you could come up with the idea that the output

c from class Z

will occur. But this is no true, because the c method in class X is a private method. Since it's private it can't be inherited to subclasses (it even can't be seen). So there is no need that any class inheriting from X also has the c method. Is it true, that because of that the call of c from method a leads to a call to the c method in class X rather than in class Z?

So recapitulating: Is my explanation from above correct or am I missing anything? I just a little bit confused, that although my instance is from class Z, calling method c from inside method a leads to the following result:

b from class Z
c from class X

My first idea was that the output looks like:

b from class Z
c from class Z

Hopefully I described the problem in a way somebody can help me now. Thank you for all replies.

¿Fue útil?

Solución

It is true that this will be printed:

c from class X

because c is private in X, and private methods aren't inherited in Java.

A subclass does not inherit the private members of its parent class. However, if the superclass has public or protected methods for accessing its private fields, these can also be used by the subclass.

So, even though X's method a calls the c method, it can only call the c method in X. The presence of another method called c in Z doesn't matter; a can only call the c method in X. The c method in Z does not override the c method in X, because it's private.

The only way to call the c method in Z is to have a Z reference and to call it directly, because it's not private.

Z z = new Z();
z.c();

which will print

c from class Z

Otros consejos

Yes you are right. In class X in method a():

void a() {
    b();
    c();
}

Only method c() from class X is visible. It's because from inside class X, class Z cannot be seen.

the compiler can resolve statically that c() its a private method inside de X class, there is no need to dynamic resolution and this implies that there is no polymorphic behavior for private methods.

Thinks in c() as a part of the implementation of a(), its a implementation detail, imagine for a moment that you change the name from c to c1 inside X, ¿you expect a different behavior for changing a private method name in a class?, the language must ensure that a change like that don't have effect on the children.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top