简体   繁体   English

如何在不使用 super() 的情况下访问父 class 的重写方法?

[英]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.如下所示,我尝试将子类的 object 转换为其父类 class 的 object。 That went well.那进展顺利。 But, when I try to access the overridden method of the parent class, it doesn't happen.但是,当我尝试访问父 class 的覆盖方法时,它不会发生。 Instead the overriding method in the child class is called.而是调用子 class 中的覆盖方法。 I know I can do this using the super keyword, but I just want to know why this can't be done by casting?我知道我可以使用 super 关键字来做到这一点,但我只想知道为什么这不能通过强制转换来完成?

This is the parent class:这是父 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:这是子 class,其属性继承自父 class:

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

This is the class which contains the main method:这是包含主要方法的 class :

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 .在您的示例中, object 始终为Child Casting is applied only to the reference variable.强制转换仅适用于引用变量。 This casting never impacts the actual object.这种铸造永远不会影响实际的 object。

Options选项

  1. As mentioned by others, add a separate method that will call super.() or use hiding.正如其他人所提到的,添加一个单独的方法,该方法将调用super.()或使用隐藏。 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这将 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.您不能直接从子 class 访问覆盖的方法。 The best you can do is add another function to your child that calls the parent print function.您可以做的最好的事情是向您的孩子添加另一个 function,它调用父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.覆盖是对 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.如果您有特定的要求来按照强制转换进行操作,则该方法必须是 class 级别“静态”而不是实例级别。

You would loose the beauty of true inheritance and enter in hiding it more.你会失去真正的 inheritance 的美丽,并更多地隐藏它。 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.借助 java.lang.invoke.MethodHandles、java.lang.invoke.MethodHandle 和 Z93F725A07423FE1C889F448B33D21F448B33D21 F446 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());
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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