Understanding inheritance in Java
Please don't be angry if my question is stupid)
I have some 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 run it, the following line is printed:
Testing parent... child::test
I can't figure out why the test
c method Parent
is called when we have an instance Child
? Can anyone help me with this?
source to share
1) The class Child
overrides (overrides) the method test
. (Polymorphism)
2) In the class, Tester
methods test(Parent obj)
and are test(Child obj)
overloaded. When you call a method, a method with the appropriate type is selected.
3) at the moment the t.test(obj)
variable obj
has an explicitly defined type Parent
, so the appropriate method will be selected and "Testing the parent ..." will be printed.
4) at the moment in time, the obj.test()
test method of the class will be called Child
, since this is polymorphism
source to share
You create a Child object using a Parent link like
Parent obj = new Child(); // obj has Child and Parent both type
System.out.println(obj instanceof Parent); // it returns true
And matrod questioning the parents of the parents,
public static class Child extends Parent{
public void test(){ //overriding here
System.out.println("child::test");
}
}
when you call 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 it catches:
public void test(Parent obj){ // catches here
System.out.println("Testing parent..."); // Here is your first output
obj.test();
}
then obj has an 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 the name of the test method of the Child class then it calls the test method of the parent class and the output will be
Testing parent...
parent::test
source to share
Because you are calling
Parent obj = new Child();
t.test(obj); //object created by Parent reference
This is obj from parent , so it will call "Testing parent" from the Tester class.
Then, thanks to polymorphism , it will also call "child :: test" from the Child class, because it is overridden.
Try to call:
Child obj = new Child();
t.test(obj);
And you will see:
"Testing child..."
"child::test"
You should also place the @Override method in the test () method of the Child class.
source to share
This is because you are calling the tester method with the Parent argument type. But the actual object is inside, the concrete implementation is Child. Perhaps these are not good words to describe, I hope you understand.
If you called typeof (obj) it will return Parent. If you are debugging your application, you will see that the method called is the one that has a parent argument, because you are passing an argument that is of type parent.
The more specific the Object is Child (in fact you can draw obj to Child and it will work fine because it is a child from the inside). And when you do obj.test (), it will call the method from child because it is being overridden by the child.
source to share
The decision to name Tester.test(Parent obj)
is done at compile time . At compile time, the compiler must choose the method signature (not the implementation, but the signature). The compiler sees two methods with the same name but different signatures, it can only choose the signature Parent
because you declared Parent obj
. That is why in the last byte code it will be represented as
find method test(Parent) in object t and execute it
The naming decision Child.test
is executed at runtime . At compile time, the compiler only finds one signature for the method test (despite the two different implementations in Parent / Child, the signature is the same). Thus, the actual implementation of both methods in the Tester class will be:
find method test() in object obj and execute it
So, even though the Tester.test (Parent) method is called, it will still try to find the test method in the passed object, once you pass the child-child version it will actually be executed.
source to share