简体   繁体   中英

How to access overridden method of parent class without using super()?

As shown below, I tried to cast the object of the sub-class to that of its parent class. That went well. But, when I try to access the overridden method of the parent class, it doesn't happen. Instead the overriding method in the child class is called. I know I can do this using the super keyword, but I just want to know why this can't be done by casting?

This is the parent class:

public class Parent {
    public void print() {
        System.out.println("In parent");
    }
}

This is the child class which has its properties inherited from the parent class:

public class Child extends Parent{
    public void print() {
        System.out.println("In child");
    }
}

This is the class which contains the main method:

public class Main {

    public static void main(String[] args) {
        Child child = new Child();
        ((Parent)child).print();
    }

}

Clarification

In your example, the object is always Child . Casting is applied only to the reference variable. This casting never impacts the actual object.

Options

  1. As mentioned by others, add a separate method that will call super.() or use hiding. Hiding is not actually overriding.

Beware of the side effects of hiding

public class AccessParent {
    public static void main(String[] args) {
        Parent p = new Child();
        p.methodC();
        System.out.println(new String(new char[20]).replace("\0", "-"));
        p.methodD();
    }
}

class Parent {
    void methodA() {
        System.out.println("Parent.methodA");
    }

    private void methodB() {
        System.out.println("Parent.methodB");
        // this will still call Child.methodA
        // a hidden method can not control the scope of overridden method
        methodA();
    }

    void methodC() {
        System.out.println("Parent.methodC");
        methodB();
    }

    void methodD() {
        System.out.println("Parent.methodD");
        // hidden method will be called
        // technically Child.methodB() is not overridden
        methodB();
    }
}

class Child extends Parent {
    @Override
    void methodA() {
        System.out.println("Child.methodA");
    }

    // this not overridden
    void methodB() {
        System.out.println("Child.methodB");
    }
}

This will output

Parent.methodC
Parent.methodB
Child.methodA
--------------------
Parent.methodD
Parent.methodB
Child.methodA```

You can't access a overriden method directly from a child class. The best you can do is add another function to your child that calls the parent print function.

public class Child extends Parent{
    public void print() {
        System.out.println("In child");
    }
    
    public void printParent() {
        super.print()
    }
}

Then you can access it like this,

public class Main {
    public static void main(String[] args) {
        Child child = new Child();
        child.printParent();
    }
}

Overriding is a principle which gives weightage on inheritance.

If you have a specific requirement to behave as per the casting then the method must be class level "static" instead of instance level.

You would loose the beauty of true inheritance and enter in hiding it more. However, the same can be achieved in casting way

package com.company.language;

public class InheritanceTrial {
    public static void main(String[] args) {
        Child child = new Child();
        child.print();
        ((Parent)child).print();
    }
}
class Parent {
    public static void print() {
        System.out.println("In parent");
    }
}

class Child extends Parent{
    public static void print() {
        System.out.println("In child");
    }
}

With the help of java.lang.invoke.MethodHandles, java.lang.invoke.MethodHandle and java.lang.invoke.MethodType we can only access the immediate parent's method. So this might help your question.

Working solution

public class Child extends Parent {
  public static void main(String[] args) throws Throwable {
      MethodHandle MH_Parent = MethodHandles.lookup().findSpecial(Parent.class, "print" , MethodType.methodType(void.class), Child.class);
      MH_Parent.invokeExact(new Child());
  }
    public void print() {
        System.out.println("In child");
    }
}

class Parent {
    void print() {
        System.out.println("In parent");
    }
}

Failing Solution

class Parent {
    public void print() {
        System.out.println("In parent");
    }
}

class Child extends Parent{
    public void print() {
        System.out.println("In child");
    }
}

public class Main {
    public static void main(String[] args) throws Throwable {
      MethodHandle MH_Parent = MethodHandles.lookup().findSpecial(Parent.class, "print" , MethodType.methodType(void.class), Child.class);
      MH_Parent.invokeExact(new Child());
    }
}

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