Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't seem to understand complex polymorphism

I'm studying CS and we have questions about polymorphism that I cant wrap my mind around. Here is an example:

public class AA{
    public AA(){
        foo();
    }
    private void foo() {
        System.out.print("AA::foo ");
        goo();
    }
    public void goo(){
        System.out.print("AA::goo ");
    }
}

public class BB extends AA{
    public BB(){
        foo();
    }
    public void foo(){
        System.out.print("BB:foo ");
    }
    public void goo(){
        System.out.print("BB::goo ");
    }
    public static void main(String[] args){
        // Code goes here
    }
}

When in void main i add the line:

AA a = new BB();

it goes first AA constructor prints AA:foo but then goo() sends it to BB's goo, why so?

Simple polymorphism such as "Animal -> cat/spider/dog" is easy to understand but when it comes to this I'm just lost. Can you guys give me any tips how to read this code? What are the rules are?

EDIT: there is no @Override annotation because this is a question from an exam.

like image 300
ronka Avatar asked Feb 20 '18 09:02

ronka


People also ask

How to understand polymorphism in Java?

To put it simply, polymorphism in Java allows us to perform the same action in many different ways. Any Java object that can pass more than one IS-A test is polymorphic in Java. Therefore, all the Java objects are polymorphic as it has passed the IS-A test for their own type and for the class Object.

Why do we need polymorphism?

Polymorphism is considered one of the important features of Object-Oriented Programming. Polymorphism allows us to perform a single action in different ways. In other words, polymorphism allows you to define one interface and have multiple implementations.

What is polymorphism how can we achieve it?

Polymorphism is the ability of an object to take on many forms. The most common use of polymorphism in OOP occurs when a parent class reference is used to refer to a child class object. Any Java object that can pass more than one IS-A test is considered to be polymorphic.

What is polymorphism in simple words in Java?

Polymorphism means "many forms", and it occurs when we have many classes that are related to each other by inheritance. Like we specified in the previous chapter; Inheritance lets us inherit attributes and methods from another class. Polymorphism uses those methods to perform different tasks.


Video Answer


2 Answers

Explanation

public class AA {

    private void foo() { ... }
    ^^^^^^^

}

Polymorphism is not applied to private methods. A subclass does not inherit private methods, so they cannot be overridden:

A class C inherits from its direct superclass all concrete methods m (both static and instance) of the superclass for which all of the following are true:

  • m is a member of the direct superclass of C.
  • m is public, protected, or declared with package access in the same package as C.
  • No method declared in C has a signature that is a subsignature of the signature of m.

Java Language Specification - 8.4.8. Inheritance, Overriding, and Hiding

Therefore, the foo() call from the A constructor doesn't invoke BB#foo, it calls AA#foo.

But the goo() call within AA#foo refers to the overridden method BB#goo. Here, with public methods, method overriding and polymorphism were applied.


It's a bit tricky, so I would recommend you put the @Override annotation everywhere it's supposed to be.

public class BB extends AA {

    @Override   // it doesn't compile - no overriding here
    public void foo() { ... }
    @Override   // it does override
    public void goo() { ... }

}

It also might be helpful to detect another problem:

Programmers occasionally overload a method declaration when they mean to override it, leading to subtle problems. The annotation type Override supports early detection of such problems.

If a method declaration in type T is annotated with @Override, but the method does not override from T a method declared in a supertype of T, or is not override-equivalent to a public method of Object, then a compile-time error occurs.

Java Language Specification - 9.6.4.4. @Override

Illustration

If a constructor body does not begin with an explicit constructor invocation and the constructor being declared is not part of the primordial class Object, then the constructor body implicitly begins with a superclass constructor invocation super();, an invocation of the constructor of its direct superclass that takes no arguments.

Java Language Specification - 8.8.7. Constructor Body

To put it simply,

public BB() {
    foo();
}

turns into

public BB() {
    super();
    foo();
}

Keeping super(); in mind, we can make the next illustration:

new BB()
        AA()                       // super(); -> AA constructor
                A#foo()            // private method call 
                        B#goo()    // polymorphic method call
        BB()                       // BB constructor
                B#foo()            // plain method call 
like image 56
Andrew Tobilko Avatar answered Oct 08 '22 17:10

Andrew Tobilko


It's explained very well in the official docs:

https://docs.oracle.com/javase/tutorial/java/IandI/super.html

If a constructor does not explicitly invoke a superclass constructor, the Java compiler automatically inserts a call to the no-argument constructor of the superclass. If the super class does not have a no-argument constructor, you will get a compile-time error. Object does have such a constructor, so if Object is the only superclass, there is no problem.

So, the Java compiler is adding super() without args for you.

In fact, if the class you are extending doesn't have a default constructor you will be required to call this constructor with args before.


Otherwise, the reason why AA:goo is not being called is because is override by BB even if it doesn't have the @Override annotation, if you want to see that call you need to use super(); in your b:goo method. In fact, the foo is not override because it private so it's not possible to override it, if you try to add the annotation @Override you'll se you have a compilation failure.

like image 37
Pau Avatar answered Oct 08 '22 17:10

Pau