Why am I 'calling' the subclass method?

10
public class A { 
  public String imprimir() {
  return "A";
       }
}

 public class B extends A { 
   public String imprimir() {
  return "B";
        }
 }

public class C extends B { 
   public String imprimir() {
  return "C";
        }
 }



public class Executa{


  public static void main (String[] args){

   A v1 = new A();
    System.out.println(v1.imprimir());


   A v2 = new B();
    System.out.println(v2.imprimir());

   A v3 = new C();
    System.out.println(v3.imprimir());


    System.out.println(((A)v3).imprimir());
    System.out.println(((B)v3).imprimir());


  }

}

Apparently a well-understood and easy-to-understand code, but it confused me a lot.

Why on the lines

System.out.println(((A)v3).imprimir());
System.out.println(((B)v3).imprimir());

is 'calling' the subclass method? Should not you call class A and class B methods respectively?

I think I'm wrong in some concept of object orientation, but in what concept?

    
asked by anonymous 05.09.2018 / 20:39

3 answers

9

The polymorphism is just the opposite of what you think it is. It indicates that the concrete object is what determines what will be executed and not the type that is waiting.

Without the polymorphism, what you are expecting would happen, so it would always call the type determined for use in that operation. In his example without the polymorphism he would print the type method so he would print "A" and "B" because the type is in charge.

If you want to print "A" you have to create an object of type A . If the object is C many things in it may be different than it should be in A , they are not substitutable in both directions. C replaces A perfectly because it has everything from A to something else. A can not replace C because it does not have all that C has.

If you try in your code it might even work because you are seeing that it has everything, but for the compiler it is tricky to know, it has to go the safe way and if it has error potential, it does not compile until because even if today is ok, one day you can change and then break all contracts.

As for using super it is a contextual keyword and only works inside the inherited class, it is not possible to use object consumption, it is something to indicate to the compiler what to pick up when there is ambiguity or lack of information what is available, the object does not exist. And it would not make sense for what I showed above.

    
05.09.2018 / 21:01
5

As already mentioned, casting does not change the object - it passes a "message" to the compiler that in that context it can consider that object to be that class.

But at runtime, the method called is that of the object itself - in the above case, the C.imprimir . If the called method did not exist in the superclass (that is, if imprimir was only defined for classes B and C, the compiler would give an error - since it would not be able to generate code to call the imprimir method of an object of the class A.

Now, regarding your concern for "not understanding some concept of object orientation": be calm - you understood O.O. - casting which is something the Java language borrows from C which is not very "object-oriented", but rather as a mechanism to allow the compiler to find itself in some cases.

If it were in Python for example, another object-oriented language - in Python there is no casting - but you can always call methods in the class itself by passing the instance explicitly - in this case, what you are trying to do would work: / p>

class A:
    def i(self):
        return "A"
class B(A):
    def i(self):
        return "B"
b = B()
print(b.i())
print(A.i(b))

It prints output B and A - that is, if the method is called in the instance, as is required in Java syntax, the parameter self , equivalent to this , is populated by the language itself - but you have the option to call the method from the class - A.i() - and in that case has to pass what would be self explicitly - then it is possible to call superclass methods in subclass instances.

The super of Java can not give you a direct reference to superclass methods if used outside of subclasses. It exists inside a method, with no arguments, so it assumes it points directly to the object in the superclass, but if you tried to use super from within Executa , it would look for the imprimir method in some superclass of Executa , and not C . (Again, super() of Python allows you to explicitly pass the class and the instance from which you want to access the attributes of the superclass.In the above example, the call below prints A )

print(super(B, b).i())

The ideal would be a way to convert your objects to the desired class, and the only clean way to do this is to have an explicit method for conversion, which is called in the subclass and returns an object of the desired class.

I found in SOen a similar question, where the answers, including using reflection, indicate that it is not really possible to call a superclass method from an instance of a subclass: link

    
05.09.2018 / 21:14
-5

In Java, all methods are virtual. Once you override a method, the new implementation is final.

    
06.09.2018 / 16:51