我读了这个问题,并认为如果有人可以这样写,这个问题就很容易解决(并不是说没有它就不能解决):

@Override
public String toString() {
    return super.super.toString();
}

我不确定它在很多情况下是否有用,但我想知道为什么它没有,以及其他语言中是否存在类似的东西。

你们怎么看?

编辑: 澄清一下:是的,我知道,这在Java中是不可能的,我并不真的怀念它。这不是我期望的工作,并惊讶地得到一个编译器错误。我只是有了个想法,喜欢讨论一下。


当前回答

使用反射,似乎至少可以获得超类的超类的类,尽管不一定是它的实例;如果这可能是有用的,请考虑Javadoc http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Class.html#getSuperclass()

其他回答

我认为如果你重写了一个方法,并想要它的所有超类版本(比如,说for equals),那么你实际上总是想先调用直接的超类版本,如果它愿意,后者会依次调用它的超类版本。

我认为这没什么意义(如果有意义的话)。我想不出有什么情况)来调用某个方法的任意超类版本。我不知道这在Java中是否可行。它可以在c++中完成:

this->ReallyTheBase::foo();

它违反了封装。你不应该能够绕过父类的行为。有时能够绕过自己类的行为(特别是在同一个方法中),但不能绕过父类的行为是有意义的。例如,假设我们有一个基类“项目的集合”,一个子类表示“红色项目的集合”,该子类的一个子类表示“大红色项目的集合”。这是有道理的:

public class Items
{
    public void add(Item item) { ... }
}

public class RedItems extends Items
{
    @Override
    public void add(Item item)
    {
        if (!item.isRed())
        {
            throw new NotRedItemException();
        }
        super.add(item);
    }
}

public class BigRedItems extends RedItems
{
    @Override
    public void add(Item item)
    {
        if (!item.isBig())
        {
            throw new NotBigItemException();
        }
        super.add(item);
    }
}

这很好- RedItems总是可以确信它包含的项目都是红色的。现在假设我们能够调用super.super.add():

public class NaughtyItems extends RedItems
{
    @Override
    public void add(Item item)
    {
        // I don't care if it's red or not. Take that, RedItems!
        super.super.add(item);
    }
}

现在我们可以添加任何我们喜欢的东西,而RedItems中的不变量被打破了。

明白吗?

我没有足够的声誉来评论,所以我将把这个添加到其他答案中。

乔恩·斯基特用一个漂亮的例子回答得很好。Matt B有一个观点:不是所有的超类都有超类。如果你调用一个没有super的super,你的代码就会崩溃。

面向对象编程(Java就是面向对象编程)是关于对象的,而不是函数。如果你想要面向任务的编程,选择c++或其他语言。如果你的对象不适合它的父类,那么你需要将它添加到“祖父类”,创建一个新类,或者找到另一个它适合的父类。

就我个人而言,我发现这种限制是Java最大的优势之一。与我使用过的其他语言相比,代码有点僵硬,但我总是知道会发生什么。这有助于实现Java“简单而熟悉”的目标。在我的脑海里,打电话给上级。超级不简单也不熟悉。也许开发者也有同感?

我认为这是一个打破继承协议的问题。 通过扩展一个类,你服从/同意它的行为、特征 而当调用super.super.method()时,你想要打破你自己的服从协议。

你不能从超类中挑选。

然而,可能会出现需要调用super.super.method()的情况——在您的代码或继承的代码中,这通常是一个糟糕的设计标志! 如果不能重构超类和超超类(一些遗留代码),则选择复合而不是继承。 封装破坏是指通过破坏封装的代码@Override一些方法。 标记了设计为不被覆盖的方法 决赛。

在c#中,你可以像这样调用任何祖先的方法:

public class A
    internal virtual void foo()
...
public class B : A
    public new void foo()
...
public class C : B
    public new void foo() {
       (this as A).foo();
    }

你也可以在Delphi中这样做:

type
   A=class
      procedure foo;
      ...
   B=class(A)
     procedure foo; override;
     ...
   C=class(B)
     procedure foo; override;
     ...
A(objC).foo();

但是在Java中,你只能通过一些设备来实现这样的聚焦。一种可能的方法是:

class A {               
   int y=10;            

   void foo(Class X) throws Exception {  
      if(X!=A.class)
         throw new Exception("Incorrect parameter of "+this.getClass().getName()+".foo("+X.getName()+")");
      y++;
      System.out.printf("A.foo(%s): y=%d\n",X.getName(),y);
   }
   void foo() throws Exception { 
      System.out.printf("A.foo()\n");
      this.foo(this.getClass()); 
   }
}

class B extends A {     
   int y=20;            

   @Override
   void foo(Class X) throws Exception { 
      if(X==B.class) { 
         y++; 
         System.out.printf("B.foo(%s): y=%d\n",X.getName(),y);
      } else { 
         System.out.printf("B.foo(%s) calls B.super.foo(%s)\n",X.getName(),X.getName());
         super.foo(X);
      } 
   }
}

class C extends B {     
   int y=30;            

   @Override
   void foo(Class X) throws Exception { 
      if(X==C.class) { 
         y++; 
         System.out.printf("C.foo(%s): y=%d\n",X.getName(),y);
      } else { 
         System.out.printf("C.foo(%s) calls C.super.foo(%s)\n",X.getName(),X.getName());
         super.foo(X);
      } 
   }

   void DoIt() {
      try {
         System.out.printf("DoIt: foo():\n");
         foo();         
         Show();

         System.out.printf("DoIt: foo(B):\n");
         foo(B.class);  
         Show();

         System.out.printf("DoIt: foo(A):\n");
         foo(A.class);  
         Show();
      } catch(Exception e) {
         //...
      }
   }

   void Show() {
      System.out.printf("Show: A.y=%d, B.y=%d, C.y=%d\n\n", ((A)this).y, ((B)this).y, ((C)this).y);
   }
} 

objC.DoIt()结果输出:

DoIt: foo():
A.foo()
C.foo(C): y=31
Show: A.y=10, B.y=20, C.y=31

DoIt: foo(B):
C.foo(B) calls C.super.foo(B)
B.foo(B): y=21
Show: A.y=10, B.y=21, C.y=31

DoIt: foo(A):
C.foo(A) calls C.super.foo(A)
B.foo(A) calls B.super.foo(A)
A.foo(A): y=11
Show: A.y=11, B.y=21, C.y=31