简体   繁体   中英

Call BaseClass method on ExtendedClass object when defined as BaseClass

Imagine following code:

public class BaseClass {
    private int a;

    public void noReturnNoParam() {
        System.out.println("From Base Class");
    }
}

public class ExtendedClass extends BaseClass {
    private int b;

    @Override
    public void noReturnNoParam() {
        System.out.println("From Extended Class");
    }
}

public class Polymorph {
    public static void main(String... args) {
        BaseClass bc = new BaseClass();
        ExtendedClass ec = new ExtendedClass();
        BaseClass bcec = new ExtendedClass();

        bc.noReturnNoParam();
        ec.noReturnNoParam();
        bcec.noReturnNoParam();
    }
}

Output is as follows:

From Base Class
From Extended Class
From Extended Class

So how can I achieve that, on calling bcec.noReturnNoParam() the BaseClass` method is called? (and only if the ExtendedClass object is stored in a BaseClass type)?

This is demonstration of one of the base principles OOP. It is called polymorphism .

Independent of how your class(BaseClass in your example) looks like it will work as it class which was used for initialisation(ExtendedClass).

This is called Dynamic Polymorphism \\ Dynamic method binding in which at runtime, JVM call method of object type, NOT reference type. In this case object type is ExtendedClass , hence its calling method from that class. And you cant avoid it.

This is not what intended from Polymorphism . Any way you can make your extended class to call its super class implementation in its method like

@Override
public void noReturnNoParam() {
    super.noReturnNoParam();    // here base class implementation will be run
    System.out.println("From Extended Class");
}

But you cannot make it to call only base class implementation.

The Java virtual machine (JVM) calls the appropriate method for the object that is referred to in each variable. It does not call the method that is defined by the variable's type. This behavior is referred to as virtual method invocation and demonstrates an aspect of the important polymorphism features in the Java language.

The issue you are having is with static vs dynamic binding .

With dynamic binding, methods will be dynamically called at run-time. Here's a good little article to read if you need clarification.

To my knowledge, you wont be able to strictly call the base method the way your classes are currently designed. Only from the derived class' method can you call the base class' since you are overriding it.

So, even though you are declaring it for the compiler as the base class, the object is really an object of the derived class, and as such, its methods will be called during run-time.

That's exactly the concept of polymorphism:

BaseClass bcec = new ExtendedClass();

BaseClass is the contract you declared for bcec. It give your compile time information about what you can get from bcec. It tells you that you can call noReturnNoParam method.

ExtendedClass is the actually implementation of bcec. JVM know at runtime that bcec.noReturnNoParam() is invoking the noReturnNoParam in ExtendedClass.

The below statement is similar:

ExtendedClass ec = new ExtendedClass();

ExtendedClass on the left is the contract, tells you what you can get from ec. ExtendedClass on the right is the actual implementation, which is executed at runtime.

ExtendedClass extends BaseClass, so an instance of ExtendedClass is also an instance of BaseClass. But an instance of BaseClass might not be an instance of ExtendedClass. That's why the below cannot compile:

ExtendedClass abc = new BaseClass();

I give you another example to make the concept less abstract.

class Fruit {
    void taste() {
        System.out.println("delicious!");
    }
}

class Apple extends Fruit{
    void taste() {
        System.out.println("sweet!");
    }
}

class Orange extends Fruit{
    void taste() {
        System.out.println("juicy!");
    }
}

class Polymorph {
    public static void main(String... args) {
        Fruit fruit = new Fruit();
        Apple apple = new Apple();
        Fruit fruit_apple = new Apple();
        Fruit fruit_orange = new Orange();

        fruit.taste(); // prints delicious!
        apple.taste(); // prints sweet!
        fruit_apple.taste(); // prints sweet!
        fruit_orange.taste(); // prints juicy!
    }
}

Orange and Apple are both Fruit. Fruit/Orange/Apple all have tastes, and Orange and Apple have their own tastes. You say an apple is a kind of fruit, an orange is also a kind of fruit, but you can't say a fruit is an apple.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM