Why am I calling the subclass method?

Asked

Viewed 341 times

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 code very didactic and easy to understand, 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? It should not call, respectively, the class A and class B methods?

I believe I’m missing some concept of object orientation, but what concept?

  • The fact of casting does not make the object type C become A nor B. He remains C. Remember that cast is not conversion, you are not converting types, you are just using polyformism, since C is also a kind of A and also B.

  • Thanks @Articuno already managed to clarify the ideas here! but to call the superclass method A, should use super ? Thanks in advance

3 answers

11


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 would happen what is expected, so he would always call the type determined for use in that operation. In his example without polymorphism he would print the type method, then 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 from what it should be in A, they are not replaceable in both directions. C replaces A perfect way because he has everything from A and something else. A cannot replace C because he doesn’t have everything C has.

If you try in your code it could even work because you are seeing that you have everything, but for the compiler it is complicated to know this, it has to go the safest way and if it has potential error it does not let compile, even though today is ok, one day can change and then break all contracts.

As to using the super it is a contextual keyword and only works within the inherited class, it is not possible to use in object consumption, it is something to indicate to the compiler what to pick up when there is ambiguity or lack of information of what is available, in the object there is this. And it wouldn’t even make sense from what I showed above.

6

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

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

Now, as for your concern of "not understanding any concept of object orientation": rest assured - you understood O.O. - the "casting" which is something that the Java language borrows from C which is not something very "object-oriented", and, yes, more like 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 explicitly passing the instance - in this case, which you are trying to do would work:

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

Print 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 filled in by the language itself - but you have the option to call the method from the class - A.i() - and in that case have to pass what would be the self explicitly - then it is possible to call superclass methods in instances of subclasses.

The super of Java cannot give you a direct reference to the methods of the superclass if used outside the subclasses. It exists within a method, without arguments, so it assumes points directly to the object in the super-class, but if you tried to use super from within Executa, he would look for the method imprimir in some super-class of Executa, and not of C. (Again, the super() de Python lets you explicitly pass the class and instance from which you want to access the attributes of the superclass. In the example above, 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 really not possible to call a super-class method from an instance of a subclass: https://stackoverflow.com/questions/5411434/how-to-call-a-superclass-method-using-java-reflection

-5

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

Browser other questions tagged

You are not signed in. Login or sign up in order to post.