Reputation: 900
If I have 2 classes, one being the parent with the following:
public class Parent {
...
public void method1() {
method2();
}
public void method2() {
}
}
And then in the subclass
public class Child extends Parent {
...
public void method2() {
...
}
}
If I run the following code:
Child c = new Child();
c.method1();
Which version of method2 gets called?
Upvotes: 1
Views: 2331
Reputation: 16209
I have some more questions for you:
public interface CanDoMethod1 {
public void method1();
}
public class Parent implements CanDoMethod1 {
public void method1() {
System.err.println("Parent doing method1");
}
}
public class Child extends Parent {
public void method1() {
System.err.println("Child doing method1");
}
}
Now you run the following code:
CanDoMethod1 instance = new Parent();
instance.method1();
What is the output?
And when you run:
CanDoMethod1 instance = new Child();
instance.method1();
Then what is the output?
And when you run:
Parent instance = new Child();
instance.method1();
Then what is the output? Why is no cast needed here?
And when you run:
Child instance = (Child) new Parent();
instance.method1();
Does this compile? If so, then what is the output?
In summary, notice that the method called is always the method of the implementation class you created, no matter what you cast or assign it to.
Upvotes: -1
Reputation: 16037
public class Parent {
public void method1() {
method2();
}
public void method2() {
System.out.println("parent m 2");
}
}
public class Child extends Parent {
public void method2(){
System.out.println("child m 2");
}
}
public class Main {
public static void main(String[] args) {
Child c = new Child();
c.method1();
System.out.println("________________");
c.method2();
}
}
And the output will be:
child m 2
________________
child m 2
Upvotes: 0
Reputation: 11999
Once you've created an object of type Child
, that's its runtime type. This won't change, regardless of casts or whatever you do to it. When you call a method, the implementation of that runtime type is going to be executed. If that type doesn't have an implementation of its own, it'll delegate to the parent class.
Even though you call method1
which was defined in Parent
, once that method calls method2
it'll resolve to the implementation of the runtime type of the object. If that's Child
, then that's the class' method which will be called.
Mind that this dynamic behaviour is different than selecting a method based on parameter types, which is done statically. Take the following, with your class definitions...
public void methodTest(Parent p) {} //Let's call this "first method"
public void methodTest(Child c) {} //Let's call this "second method"
Parent p = new Parent();
Child c = new Child();
//Assume a is a variable of some type that implements the above methods
a.methodTest(p); //Will call first method
a.methodTest(c); //Will call second method
a.methodTest((Parent)c); //WILL CALL FIRST METHOD!
So selecting a method based on parameter types is done statically. It won't select a different method based on runtime type.
But selecting a method based on what object it's being called on depends on that object's runtime type. That's what allows us to override method behaviour in subclasses.
Upvotes: 3
Reputation: 420921
All methods are virtual in Java, which means that it is the Child.method2
that will be called (even if the call is done from the context of Parent
).
If the correctness of Parent.method1
relies on the implementation of method2
, you should design it differently:
public class Parent {
...
public void method1() {
method2impl();
}
public void method2() {
method2impl();
}
// make it private or final.
public final method2impl() {
...
}
}
Upvotes: 7