3

Please don't be angry if my question is stupid )

I have a piece of code:

public class LinkageTest { 

public static class Parent { 

    public void test() { 
        System.out.println("parent::test"); 
    } 
} 

public static class Child extends Parent { 

    public void test() { 
        System.out.println("child::test"); 
    } 
} 

public static class Tester { 

    public void test(Parent obj) { 
        System.out.println("Testing parent..."); 
        obj.test(); 
    } 

    public void test(Child obj) { 
        System.out.println("Testing child..."); 
        obj.test(); 
    } 
} 

public static void main(String[] args) { 
    Parent obj = new Child(); 
    Tester t = new Tester(); 
    t.test(obj); 
} 

}

When I'm running it, the next string is printed:

Testing parent... child::test

I can't understand why test method with Parent is called if we have instance of Child? Can some one help me with it?

5 Answers 5

3

1) The class Child redefines (overriding) the test method. (polymorphism)

2) In the Tester class, the test(Parent obj) and test(Child obj) methoda are overloaded. When you call the method, the method with the appropriate type is selected.

3) at the time t.test(obj), the variable obj has an explicitly defined Parent type, so the appropriate method will be selected and "Testing parent ..." printed.

4) at the time obj.test(), the test method of the Child class will be called, since this is a polymorphism

Sign up to request clarification or add additional context in comments.

Comments

1

You are creating an object of Child via Parent reference like

Parent obj = new Child(); // obj has Child and Parent both type
System.out.println(obj instanceof Parent); // it returns true

And Child overriding test mathod of Parent,

public static class Child extends Parent{ 
    public void test(){ //overriding here
        System.out.println("child::test"); 
    } 
}

while you calling t.test(obj) method

    public static void main(String[] args){ 
    Parent obj = new Child();
    Tester t = new Tester();
    t.test(obj); // obj created by Parent reference  
}

So catches by :

public void test(Parent obj){ // catches here
        System.out.println("Testing parent..."); // Here is your first output
        obj.test(); 
    }

then obj have overridden test method so it calls

public static class Child extends Parent{ 
    public void test(){ // overridden method first priority
        System.out.println("child::test"); // Here is your second output
    } 
} 

if you change Child class test method name then it calls Parent class test method,and output will be

Testing parent...
parent::test

Comments

1

Because you call

Parent obj = new Child();
t.test(obj); //object created by Parent reference

This obj is from parent, so it will call the "Testing parent" from Tester class.

Then, thanks of polymorphism, it will also call "child::test" from Child class because is overridden.

Try to call:

Child obj = new Child();
t.test(obj);

And you will see:

"Testing child..."
"child::test"

You should also put @Override on the test() method of the Child class.

Comments

0

Thats because you're calling tester method with argument type of Parent. But the actual object inside, concrete implementation is Child. These might not be good words to describe it, hope you understand.

If you've called typeof(obj), it would return Parent. If you've debugged the app, you'd see that the method called is the one with Parent argument, because you pass argument which type is Parent.

The more concrete object is Child (actually you can cast the obj Child and it will work fine, because it is child on the inside). And when you do obj.test(), it will call method from child, because it is overriden by child.

Comments

0

Decision to call Tester.test(Parent obj) is made at compilation time. During compilation compiler must pick method signature (not implementation, but signature). Compiler sees two methods with same name, but different signatures, it can pick only Parent signature because you've declared Parent obj. This is why in final byte code it will be presented like

find method test(Parent) in object t and execute it

Decision to call Child.test is made at run time. During compilation compiler finds only one signature for method test (despite two different implementations in Parent/Child, signature is the same). So actual implementation in both methods in Tester class will be:

find method test() in object obj and execute it

So, despite the fact that Tester.test(Parent) method is called, it still will try to find method test in passed object, as soon as you passed child - child's version will be actually executed.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.