Java 调用超超类方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3456177/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 00:56:39  来源:igfitidea点击:

Calling super super class method

javainheritanceoverriding

提问by Harish

Let's say I have three classes A, B and C.

假设我有三个班级 A、B 和 C。

  • B extends A
  • C extends B
  • B 扩展 A
  • C 扩展 B

All have a public void foo()method defined.

public void foo()定义了一个方法。

Now from C's foo()method I want to invoke A's foo()method (NOT its parent B's method but the super super class A's method).

现在从 C 的foo()方法我想调用 A 的foo()方法(不是它的父 B 的方法,而是超超类 A 的方法)。

I tried super.super.foo();, but it's invalid syntax. How can I achieve this?

我试过了super.super.foo();,但它的语法无效。我怎样才能做到这一点?

采纳答案by Landei

You can't even use reflection. Something like

你甚至不能使用反射。就像是

Class superSuperClass = this.getClass().getSuperclass().getSuperclass();
superSuperClass.getMethod("foo").invoke(this);

would lead to an InvocationTargetException, because even if you call the foo-Method on the superSuperClass, it will still use C.foo()when you specify "this" in invoke. This is a consequence from the fact that all Java methods are virtual methods.

会导致InvocationTargetException,因为即使您在 superSuperClass 上调用 foo-Method,C.foo()当您在 invoke 中指定“this”时它仍然会使用。这是所有 Java 方法都是虚方法这一事实的结果。

It seems you need help from the B class (e.g. by defining a superFoo(){ super.foo(); }method).

看来您需要 B 类的帮助(例如通过定义一个superFoo(){ super.foo(); }方法)。

That said, it looks like a design problem if you try something like this, so it would be helpful to give us some background: Whyyou need to do this?

也就是说,如果你尝试这样的事情,它看起来像是一个设计问题,所以给我们一些背景会很有帮助:为什么你需要这样做?

回答by Andreas Dolk

It's not possible, we're limited to call the superclass implementations only.

这是不可能的,我们只能调用超类实现。

回答by Jon Skeet

You can't - because it would break encapsulation.

你不能 - 因为它会破坏封装。

You're able to call your superclass's method because it's assumed that you know what breaks encapsulation in your ownclass, and avoid that... but you don't know what rules your superclass is enforcing - so you can't just bypass an implementation there.

您可以调用超类的方法,因为假设您知道是什么破坏了您自己的类中的封装,并避免了这种情况......在那里实施。

回答by Madhup Singh Yadav

You can't do it in a simple manner.

你不能以简单的方式做到这一点。

This is what I think you can do:

这是我认为你可以做的:

Have a bool in your class B. Now you must call B's foo from C like [super foo]but before doing this set the bool to true. Now in B's foo check if the bool is true then do not execute any steps in that and just call A's foo.

在你的班级 B 中有一个 bool。现在你必须像 C 一样调用 B 的 foo[super foo]但在此之前将 bool 设置为 true。现在在 B 的 foo 检查 bool 是否为真,然后不要执行其中的任何步骤,只需调用 A 的 foo。

Hope this helps.

希望这可以帮助。

回答by lorenzog

I smellsomething fishy here.

我在这里到一股腥味。

Are you sure you are not just pushing the envelope too far "just because you should be able to do it"? Are you sure this is the best design pattern you can get? Have you tried refactoring it?

您确定您不是“仅仅因为您应该能够做到”而将信封推得太远吗?你确定这是你能得到的最好的设计模式吗?你试过重构吗?

回答by Penny

I had a problem where a superclass would call an top class method that was overridden. This was my workaround...

我有一个问题,超类会调用被覆盖的顶级方法。这是我的解决方法...

//THIS WOULD FAIL CALLING SUPERCLASS METHODS AS a1() would invoke top class METHOD

//这将无法调用超类方法,因为 a1() 会调用顶级方法

class foo1{
 public void a1(){
  a2();
  }
 public void a2(){}
 }
class foo2 extends foo1{
 {
 public void a1(){
//some other stuff
 super.a1();
 }
 public void a2(){
//some other stuff
 super.a2();
 }

//THIS ENSURES THE RIGHT SUPERCLASS METHODS ARE CALLED //the public methods only call private methods so all public methods can be overridden without effecting the superclass's functionality.

//这确保了正确的超类方法被调用 //公共方法只调用私有方法,所以所有公共方法都可以被覆盖而不影响超类的功能。

class foo1{
 public void a1(){
  a3();}
 public void a2(){
  a3();}
 private void a3(){
//super class routine
 }
class foo2 extends foo1{
 {
 public void a1(){
//some other stuff
 super.a1();
 }
 public void a2(){
//some other stuff
 super.a2();
 }

I hope this helps. :)

我希望这有帮助。:)

回答by user2490562

Before using reflection API think about the cost of it.

在使用反射 API 之前考虑一下它的成本。

It is simply easy to do. For instance:

这很容易做到。例如:

C subclass of B and B subclass of A. Both of three have method methodName() for example.

B 的 C 子类和 A 的 B 子类。例如,这三个都有方法 methodName()。

public abstract class A {

   public void methodName() {
     System.out.println("Class A");
   }

}


public class B extends A {

   public void methodName() {
      super.methodName();
      System.out.println("Class B");
   }

   // Will call the super methodName
   public void hackSuper() {
      super.methodName();
   }

}

public class C extends B {

   public static void main(String[] args) {
      A a = new C();
      a.methodName();
   }

  @Override
  public void methodName() {
      /*super.methodName();*/
      hackSuper();
      System.out.println("Class C");
  }

}

Run class C Output will be: Class A Class C

运行 class C 输出将是: Class A Class C

Instead of output: Class A Class B Class C

代替输出:A 类 B 类 C 类

回答by Radu Ionescu

To quote a previous answer "You can't - because it would break encapsulation." to which I would like to add that:

引用之前的答案“你不能 - 因为它会破坏封装。” 我想补充一点:

However there is a corner case where you can,namely if the method is static(publicor protected). You can not overwrite the static method.

但是,您可以在极端情况下使用,即如果方法是static(publicprotected)。您不能覆盖静态方法

Having a public staticmethod is trivial to prove that you can indeed do this.

拥有一个public static方法来证明你确实可以做到这一点是微不足道的。

For protectedhowever, you need from inside one of your methods to perform a cast to any superclass in the inheritance path and that superclass method would be called.

对于protected然而,你从你的方法里面一个需要在继承路径进行强制转换为任何超类和超类方法将被调用。

This is the corner case I am exploring in my answer:

这是我在回答中探索的极端情况:

public class A {
    static protected callMe(){
        System.out.println("A");
    }
}

public class B extends A {
    static protected callMe(){
        System.out.println("B");
    }
}

public class C extends B {
    static protected callMe(){
        System.out.println("C");
        C.callMe();
    }

    public void accessMyParents(){
        A a = (A) this;
        a.callMe(); //calling beyond super class
    }
}

The answer remains still No, but just wanted to show a case where you can, although it probably wouldn't make any sense and is just an exercise.

答案仍然不是,但只是想展示一个你可以做到的案例,尽管它可能没有任何意义并且只是一个练习。

回答by Jainam MJ

Yes you can do it. This is a hack. Try not to design your program like this.

是的,你可以做到。这是一个黑客。尽量不要这样设计你的程序。

class A
{
    public void method()
    { /* Code specific to A */ }
}

class B extends A
{
    @Override
    public void method()
    { 
       //compares if the calling object is of type C, if yes push the call to the A's method.
       if(this.getClass().getName().compareTo("C")==0)
       { 
           super.method(); 
       }
       else{  /*Code specific to B*/  }

    }
}

class C extends B
{
    @Override
    public void method()
    { 
        /* I want to use the code specific to A without using B */ 
        super.method();

    }
}

回答by CoolMind

In my simple case I had to inherit B and C from abstract class, that incapsulates equal methods of B and C. So that

在我的简单情况下,我必须从抽象类继承 B 和 C,它封装了 B 和 C 的相等方法。所以

     A
     |
   Abstr
    / \
   B   C

While it doesn't solve the problem, it can be used in simple cases, when C is similar to B. For instance, when C is initialized, but doesn't want to use initializers of B. Then it simply calls Abstr methods.

虽然它不能解决问题,但它可以用于简单的情况,当 C 类似于 B 时。例如,当 C 被初始化,但不想使用 B 的初始化程序时,它只是调用 Abstr 方法。

This is a common part of B and C:

这是 B 和 C 的共同部分:

public abstract class Abstr extends AppCompatActivity {
    public void showProgress() {
    }

    public void hideProgress() {
    }
}

This is B, that has it's own method onCreate(), which exists in AppCompatActivity:

这是 B,它有自己的方法onCreate(),存在于AppCompatActivity

public class B extends Abstr {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState); // Call from AppCompatActivity.
        setContentView(R.layout.activity_B); // B shows "activity_B" resource.
        showProgress();
    }
}

C shows its own layout:

C 显示了它自己的布局:

public class C extends Abstr {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState); // Call from AppCompatActivity.
        setContentView(R.layout.activity_C); // C shows "activity_C" resource.
        showProgress();
    }
}