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

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

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

你们怎么看?

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


当前回答

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

你不能从超类中挑选。

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

其他回答

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

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

this->ReallyTheBase::foo();

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

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

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

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

看看这个Github项目,尤其是objectHandle变量。这个项目展示了如何实际而准确地在孙子上调用祖父母方法。

以防链接被破坏,下面是代码:

import lombok.val;
import org.junit.Assert;
import org.junit.Test;

import java.lang.invoke.*;

/*
Your scientists were so preoccupied with whether or not they could, they didn’t stop to think if they should.
Please don't actually do this... :P
*/
public class ImplLookupTest {
    private MethodHandles.Lookup getImplLookup() throws NoSuchFieldException, IllegalAccessException {
        val field = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");
        field.setAccessible(true);
        return (MethodHandles.Lookup) field.get(null);
    }

    @Test
    public void test() throws Throwable {
        val lookup = getImplLookup();
        val baseHandle = lookup.findSpecial(Base.class, "toString",
            MethodType.methodType(String.class),
            Sub.class);
        val objectHandle = lookup.findSpecial(Object.class, "toString",
            MethodType.methodType(String.class),
            // Must use Base.class here for this reference to call Object's toString
            Base.class);
        val sub = new Sub();
        Assert.assertEquals("Sub", sub.toString());
        Assert.assertEquals("Base", baseHandle.invoke(sub));
        Assert.assertEquals(toString(sub), objectHandle.invoke(sub));
    }

    private static String toString(Object o) {
        return o.getClass().getName() + "@" + Integer.toHexString(o.hashCode());
    }

    public class Sub extends Base {
        @Override
        public String toString() {
            return "Sub";
        }
    }

    public class Base {
        @Override
        public String toString() {
            return "Base";
        }
    }
}

编码快乐! !

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

你不能从超类中挑选。

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

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