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

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

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

你们怎么看?

编辑: 澄清一下:是的,我知道,这在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";
        }
    }
}

编码快乐! !

其他回答

看看这个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()

我曾经遇到过这样的情况,即体系结构是在一个公共CustomBaseClass中构建公共功能,该CustomBaseClass代表几个派生类实现。 但是,我们需要规避特定派生类的特定方法的通用逻辑。在这种情况下,我们必须使用super.super.methodX实现。

我们通过在CustomBaseClass中引入一个布尔成员来实现这一点,该成员可用于有选择地推迟自定义实现,并在需要时让位于默认框架实现。

        ...
        FrameworkBaseClass (....) extends...
        {
           methodA(...){...}
           methodB(...){...}
        ...
           methodX(...)
        ...
           methodN(...){...}

        }
        /* CustomBaseClass overrides default framework functionality for benefit of several derived classes.*/
        CustomBaseClass(...) extends FrameworkBaseClass 
        {
        private boolean skipMethodX=false; 
        /* implement accessors isSkipMethodX() and setSkipMethodX(boolean)*/

           methodA(...){...}
           methodB(...){...}
        ...
           methodN(...){...}

           methodX(...){
                  if (isSkipMethodX()) {
                       setSKipMethodX(false);
                       super.methodX(...);
                       return;
                       }
                   ... //common method logic
            }
        }

        DerivedClass1(...) extends CustomBaseClass
        DerivedClass2(...) extends CustomBaseClass 
        ...
        DerivedClassN(...) extends CustomBaseClass...

        DerivedClassX(...) extends CustomBaseClass...
        {
           methodX(...){
                  super.setSKipMethodX(true);
                  super.methodX(...);
                       }
        }

然而,在框架和应用程序中遵循良好的架构原则,我们可以通过使用hasA方法而不是isA方法轻松避免这种情况。但在任何时候,期待设计良好的架构都是不现实的,因此需要摆脱坚实的设计原则,引入像这样的技巧。 这只是我的意见……

除了其他人提出的非常好的观点之外,我认为还有另一个原因:如果超类没有超类怎么办?

因为每个类都自然地扩展(至少)Object,所以super.whatever()总是引用超类中的一个方法。但是如果你的类只扩展Object呢?超级指的是什么?该如何处理该行为-编译器错误,空指针,等等?

我认为不允许这样做的主要原因是它违反了封装,但这可能也是一个小原因。