Can anyone explain me the result of this execution? I can't notice why each method is called. And how we distinguish the real type vs the apparent type. Thank you :)
public class JavaApplication15 {
public static void main(String[] args) {
A a = new A();
B b= new B();
A ab = new B();
b.f(a);
b.f(b);
b.f(ab);
}
}
public class A {
private final String id="A";
public void f(A x){
System.out.println("Send a fax to "+ x ) ;
}
public String toString(){return id;}
}
public class B extends A{
private final String id="B";
public void f(B x){
System.out.println("Send an email to"+ x ) ;
}
public String toString(){return id;}
}
Result:
Send a fax to A
Send an email to B
Send a fax to B
In Java, objects have an actual type, which is the class whose constructor was used to create them, but objects of a class which extends another class or implements an interface are also considered to be of the type of that class or interface.
The declared type or compile-time type of a variable is the type that is used in the declaration. The run-time type or actual type is the class that actually creates the object. The variable nameList declared below has a declared type of List and an actual or run-time type of ArrayList .
Object. getClass() method is used to determine the type of object at run time. Return Type: Returns the Class objects that represent the runtime class of this object.
Note that Java supports only single, multilevel, and hierarchical types of inheritance using classes. Java does not support multiple and hybrid inheritance with classes.
An object of class B
has both f(A)
and f(B)
. When you call f(x)
, it generally chooses the most specific one that matches the type of x
. For this, what matters is the type of the reference.
So your a
is an A
, therefore it calls f(A)
. Your b
is a B
, therefore it calls f(B)
. But what is your ab
? The type of the reference is A
. So the compiler tells it to call the f(A)
overload.
But then, shouldn't it have used the ab
object as an A
and therefore printed send a fax to A
using A.toString()
rather than B.toString()
?
No, because the choice of method to be called in this case is not determined by the parameter. It's not a choice between overloads as the above choice was, it is a choice between overrides. When deciding which method to use, the one from the superclass or the one from the subclass, the actual type of the object determines it. Since the object referred to by ab
is in fact a B
, the toString()
of B
is chosen.
So - among overloaded methods, the one that is chosen is determined based on the number and type of the argument, and the the type of the argument is the type of the reference.
Among overridden methods, the one that is chosen is the one in the actual type of the object instance, regardless of what the type of the reference through which it is invoked.
Note that a method is only considered overridden if it has the same name, number of parameters and respective types of parameters as the parent method.
You are overloading which (per the wikipedia) creates multiple methods of the same name with different implementations. I think you meant to override the f(A x)
method with the f(B x)
method. Overriding (per the wikipedia) allows a subclass or child class to provide a specific implementation of a method that is already provided by one of its superclasses or parent classes.
Based on the surprise expressed in your question, I think you wanted something like
@Override
public void f(A x) {
System.out.println("Send an email to"+ x ) ;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With