Reputation: 75
public class A {
public void m1(A a) {
System.out.println("m1(A) in A");
}
public void m4() {
System.out.println("m4() in A");
}
}
public class B extends A{
public void m1(B b) {
System.out.println("m1(B) in B");
}
public void m4() {
System.out.println("m4() in B");
}
}
public class Test {
public static void main(String[] args) {
B b = new B();
A a = b;
a.m1(b); // returns m1(A) in A
a.m4(); // returns m4() in B
}
}
Can someone please explain why a.m1(b)
uses the method of A and a.m4()
uses the method of B?
I particularly don't understand how this one variable (a
) invokes methods of two different classes. I thought that at runtime, a
is either seen as an A or a B, which then should result in either both methods from A or both methods from B.
Upvotes: 0
Views: 156
Reputation: 1707
Lets start with the basics of object declaration.
Let's consider a class Animal
.
Animal anim=new Animal();
Anim anim
tells JVM to create a new reference variable of type Animal and the new Animal()
asks the JVM to create a new Animal
object. Both these statements combined by =
tells JVM to create a reference variable of type Animal
and assign a animal object to it.
What does anim
?
anim
is similar to a remote control which controls the behaviour of an object of type Animal
. We use it to refer to the object.I hope it's clear till now.
Now let us move on to Inheritance and Polymorphism. Consider a new class Dog
which extends Animal
. Dog
becomes a sub-class of Animal
.
In case of inheritance, you could consider the IS A
rule. In this case, since Dog
has extended Animal
, Dog
IS A Animal
. I hope you got me. This is where polymorphism comes into picture. Polymorphism means you can actually use a super class reference variable to refer to a sub class object.
Animal anim1=new Dog();
We have created a remote control anim1
which controls a Dog
object. This anim1
reference (remote control) can only control Animal
specific methods of class Dog
. This remote control can also control the over-ridden methods but can not control any new method in Dog
which is not inherited or over-ridden.
Now, Let us move on to your classes A
and B
. B
IS-A A
since it has extended A
.
This means A a= new B();
is true by polymorphism. This is similar to what yoh have done using the below code:
B b=new B();
A a=b;
Now why does a.m1(b);
go to method in A
and a.m4();
go to B
?
Let us look at something else before going to that:
You have a method in class A
as:
public void m1(A a)
You have a method in class B
as:
public void m1(B b)
Overriding means you are actually redefining a inherited method in the sub class. So in your case, m1(B b)
in class B
is not over-riding since the paraneter it has is different. The parameter it has is of type B
while the original m1(A a)
in A
looks for argument of type A
. In short, your class B
has 2 methods named as m1
.
One which is inherited from A
and a new method or over-loaded method with a parameter type B
.
Like I have already mentioned, our remote control a
can only see the method which is specific to class A
. It can't see the over-loaded method. That's the reason, it's actually going to the inherited method m1(A a)
.
Now, a.m4();
goes to m4()
in B
. why?
m4()
in B
is an over-ridden method and a
can see it. Had you called b.m1(b)
, method in B
would have been used.
Summing up: You can use a super class reference variable/remote to refer/point to a sub-class object but this remote can only see inherited methods including over-ridden but not over loaded. But a reference of sub class type will be able to see all the methods.
To help you identify over-ridden and overloaded methods:
Over-ridden method are like:
public
cannot be made private
.Overloaded methods like:
Returns types can be different.
There should be some change in argument type or number of arguments should be different.
Using the above rules, you can easily idebtify that m1(B b)
in B
was actually a overloaded method since the parameter type varies from m1(A a)
.
Finally, B
possessed 3 methods:
m1(A a)
inherted
m1(B b)
overloaded
m4()
over-riddenPlease comment if you have any doubts or in case of an error.
Upvotes: 1
Reputation: 140328
It's because B.m1(B)
doesn't override A.m1(A)
. It's an overload instead because its parameter is a different type.
In order to override it, you would need to change the parameter type to A
.
Note that it's always a good idea to annotate methods that you think you are overriding with @Override
: then the compiler will tell you if you aren't really overriding the method.
Note also that if you called b.m1(b);
it would call the method on B
, since that overload is more specific that A.m1(A)
. However, with the current code the only method which can be matched at compile time is A.m1(A)
, since all is known is that a
is either an instance of A
or one of its subtypes: the only methods which are known to be available are the methods on A
.
The invoked method is chosen at compile time, not runtime.
Upvotes: 4