Can't understand polymorphic method call

I have a class Pair:

public class Pair {
   public void getObject(Object o){
       System.out.println("Text from Pair");}
 }

It inherits the Detail class, which has the same method, but accepts an object of a different type:

public class Detail extends Pair {
  public void getObject(Date o){
    System.out.println("Text from Detail");}
}

In Main I have this:

Detail d = new Detail();
Pair p = d;
p.getObject(new Date());

And in fact, a polymorphic method call should be executed, but for the Detail object, the getObject method is called from the Pair class, why so? How exactly does a method call work here?

Author: Lex Hobbit, 2017-08-07

3 answers

In java, there are 3 behaviors relevant to your topic:

  • overriding (official documentation here)
  • overloading (official documentation here - section "Overloading Methods")
  • hiding (official documentation here)

Since the documentation says that:

The overriding method has the same name, number and type of parameters, and return type as the method that it overrides. An overriding method can also return a subtype of the type returned by the overridden method. This subtype is called a covariant return type.

And in your case, you have violated the rule number and type of parameters, then it turns out that it is not override. At the same time, the following is written about overload:

The Java programming language supports overloading methods, and Java can distinguish between methods with different method signatures. This means that methods within a class can have the same name if they have different parameter lists (there are some qualifications to this that will be discussed in the lesson titled "Interfaces and Inheritance").

Which applies specifically to your situation. Thus, calling the method by reference Pair p You will call the method of the Pair class, even though it is actually an object Detail.

In addition, java has a mechanism for tracking such misunderstandings in the form of @Override annotations, marking it with a method the compiler will throw an error if it is not override. In your case:

@Override
public void getObject(Date o){
    System.out.println("Text from Detail");}

The compiler will return the error "Method doesn't override method from its superclass".

Well, in the end, to achieve a real override in the Detail class, the method should look like this:

public void getObject(Object o){
    System.out.println("Text from Detail");}

In this case, you will get the expected result.

I hope I managed to explain everything in detail. Good luck in further study =).

 5
Author: Mikita Berazouski, 2017-08-07 21:23:47

In order for a function of a derived class to be considered a polymorphic variant of a function of the base class, they must match not only the names, but also the types of arguments. In your case, the two functions are considered just an overload of the name getObject. And in p.getObject(new Date()); , the Pair class is called.

Similar question

 3
Author: Nikolai, 2017-08-07 20:47:29

To understand what is happening, you need to clarify a few concepts:

  1. Re-loading. You can have 2 methods in the same class with the same name but different parameters.

  2. Redefinition. The input parameter types must match exactly.

  3. Inheritance. Provides fields and methods of the parent class

These are not definitions of the concepts of overloading, overriding, and inheritance, but only some of them points relevant to the question.

In your case, the Detail object has two variants of the getObject method, one that you explicitly defined directly in the class: public void getObject(Date o), and the second that it received from the parent as a result of inheritance : public void getObject(Object o).

When the VM needs to determine which method to call, it looks at what type of parameter you sent to the method, and based on the type of this parameter, it selects the best overload option.

Following this logic you might think that there should be a method with a parameter of type Date is called. But you do cast the types:

Detail d = new Detail();
Pair p = d; //Вот здесь. Это равнозначно Pair p = (Pair) d;
p.getObject(new Date());

And the list of methods for an object is always defined by the pointer type. And since you now have the pointer type Pair and it has only one variant of this method, it was called. Well, since he accepts Object , then Date "swallowed without wincing". And called the only method available to Pair getObject(Object).

 0
Author: Pavel, 2017-08-08 02:00:40