调用超级超类方法

时间:2010-08-11 07:23:36

标签: java inheritance override

假设我有三个A,B和C类。

  • B延伸A
  • C延伸B

所有人都定义了public void foo()方法。

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

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

12 个答案:

答案 0 :(得分:31)

你甚至不能使用反射。像

这样的东西
Class superSuperClass = this.getClass().getSuperclass().getSuperclass();
superSuperClass.getMethod("foo").invoke(this);

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

您似乎需要B类的帮助(例如,通过定义superFoo(){ super.foo(); }方法)。

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

答案 1 :(得分:20)

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

你可以调用你的超类的方法,因为它假设你知道什么打破了自己的类中的封装,并避免了......但你不知道你的超类是什么规则执行 - 所以你不能绕过那里的实施。

答案 2 :(得分:3)

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

我认为你可以这样做:

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

希望这有帮助。

答案 3 :(得分:2)

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

但是,如果方法是staticpublicprotected),则可以使用角落情况。你不能overwrite the static method

使用public static方法很难证明你确实可以做到这一点。

但是对于protected,您需要从一个方法内部对继承路径中的任何超类执行强制转换,并且将调用该超类方法。

这是我在答案中探讨的极端案例:

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
    }
}

答案仍然是“不”,但只是想展示一个可以的案例,虽然它可能没有任何意义,只是一个练习。

答案 4 :(得分:2)

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

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();

    }
}

答案 5 :(得分:0)

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

答案 6 :(得分:0)

smell有点可疑。

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

答案 7 :(得分:0)

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

//这将失败调用超级方法作为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();
 }

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

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();
 }

我希望这会有所帮助。 :)

答案 8 :(得分:0)

在使用反射API之前,请考虑它的成本。

这很简单。例如:

B的B子类和B的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");
  }

}

运行C类输出将是: A级 C级

而不是输出: A级 B级 C级

答案 9 :(得分:0)

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

     A
     |
   Abstr
    / \
   B   C

虽然它不能解决问题,但是可以在简单的情况下使用,例如C与B相似。例如,当C初始化但不想使用B的初始化器时,它只是调用摘要方法。

这是B和C的共同部分:

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

    public void hideProgress() {
    }
}

这是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显示其自己的布局:

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();
    }
}

答案 10 :(得分:0)

有一种解决方法可以解决我的类似问题:

使用A,B和C类场景,有一种方法不会破坏封装,也不需要在B类内部声明C类。解决方法是将B类的方法移到单独但受保护的方法中。

然后,如果不需要那些B类的方法,则只需重写该方法,但不要在该方法内使用“ super”。覆盖和不执行任何操作均有效地抵消了B类方法。

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

public class B extends A {
    protected void callMe() {
        super.callMe();
        methodsForB(); // Class B methods moved out and into it's own method
    }

    protected void methodsForB() {
        System.out.println("methods for B");
    }
}

public class C extends B {

    public static void main(String[] args) {
        new C().callMe();
    }

    protected void callMe() {
        super.callMe();
        System.out.println("callMe for C");
    }

    protected void methodsForB() {
        // Do nothing thereby neutralising class B methods 
    }
}

结果将是:

callMe for A
callMe for C

答案 11 :(得分:0)

这不是您通常应该做的事情,但是,在您必须解决第三方库中的某些错误(如果允许)的特殊情况下,您可以实现调用已经存在的超超类方法已使用 delegation pattern 和扩展超超类以用作桥接的内部类覆盖:

class A() {
  public void foo() {
    System.out.println("calling A");
  }
}

class B extends A() {
  @Overwrite
  public void foo() {
    System.out.println("calling B");
  }
}

class C extends B() {
  private final a;

  public C() {
    this.a = new AExtension();
  }

  @Overwrite
  public void foo() {
    a.foo();
  }

  private class AExtension extends A {
  }
}

This way you will be able to not only call the super super method but also combine calls to other super super class methods with calls to methods of the super class or the class itself by using `C.super` or `C.this`.