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

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

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

你们怎么看?

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


当前回答

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

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

this->ReallyTheBase::foo();

其他回答

看看这个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";
        }
    }
}

编码快乐! !

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

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

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

我认为乔恩·斯基特有正确答案。我只是想补充一点,你可以通过强制转换从超类的超类中访问阴影变量:

interface I { int x = 0; }
class T1 implements I { int x = 1; }
class T2 extends T1 { int x = 2; }
class T3 extends T2 {
        int x = 3;
        void test() {
                System.out.println("x=\t\t"          + x);
                System.out.println("super.x=\t\t"    + super.x);
                System.out.println("((T2)this).x=\t" + ((T2)this).x);
                System.out.println("((T1)this).x=\t" + ((T1)this).x);
                System.out.println("((I)this).x=\t"  + ((I)this).x);
        }
}

class Test {
        public static void main(String[] args) {
                new T3().test();
        }
}

它产生输出:

x=              3
super.x=        2
((T2)this).x=   2
((T1)this).x=   1
((I)this).x=    0

(例子来自JLS)

但是,这对方法调用不起作用,因为方法调用是基于对象的运行时类型确定的。

我猜,因为它不常用。我能看到使用它的唯一原因是,如果您的直接父文件覆盖了某些功能,而您试图将其恢复到原始文件。

在我看来,这似乎是违反OO原则的,因为类的直接父类应该比祖父类更接近你的类。

在我看来,这是在Java中实现super.super.sayYourName()行为的干净方法。

public class GrandMa {  
    public void sayYourName(){  
        System.out.println("Grandma Fedora");  
    }  
}  

public class Mama extends GrandMa {  
    public void sayYourName(boolean lie){  
        if(lie){   
            super.sayYourName();  
        }else {  
            System.out.println("Mama Stephanida");  
        }  
    }  
}  

public class Daughter extends Mama {  
    public void sayYourName(boolean lie){  
        if(lie){   
            super.sayYourName(lie);  
        }else {  
            System.out.println("Little girl Masha");  
        }  
    }  
}  

public class TestDaughter {
    public static void main(String[] args){
        Daughter d = new Daughter();

        System.out.print("Request to lie: d.sayYourName(true) returns ");
        d.sayYourName(true);
        System.out.print("Request not to lie: d.sayYourName(false) returns ");
        d.sayYourName(false);
    }
}

输出:

请求说谎:d.sayYourName(true)返回奶奶Fedora 请求不要说谎:d.sayYourName(false)返回小女孩玛莎