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

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

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

你们怎么看?

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


当前回答

我认为以下代码允许在大多数情况下使用super.super…super.method()。 (即使这样做很难看)

简而言之

创建祖先类型的临时实例 将字段值从原始对象复制到临时对象 在临时对象上调用目标方法 将修改后的值复制回原始对象

用法:

public class A {
   public void doThat() { ... }
}

public class B extends A {
   public void doThat() { /* don't call super.doThat() */ }
}

public class C extends B {
   public void doThat() {
      Magic.exec(A.class, this, "doThat");
   }
}


public class Magic {
    public static <Type, ChieldType extends Type> void exec(Class<Type> oneSuperType, ChieldType instance,
            String methodOfParentToExec) {
        try {
            Type type = oneSuperType.newInstance();
            shareVars(oneSuperType, instance, type);
            oneSuperType.getMethod(methodOfParentToExec).invoke(type);
            shareVars(oneSuperType, type, instance);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    private static <Type, SourceType extends Type, TargetType extends Type> void shareVars(Class<Type> clazz,
            SourceType source, TargetType target) throws IllegalArgumentException, IllegalAccessException {
        Class<?> loop = clazz;
        do {
            for (Field f : loop.getDeclaredFields()) {
                if (!f.isAccessible()) {
                    f.setAccessible(true);
                }
                f.set(target, f.get(source));
            }
            loop = loop.getSuperclass();
        } while (loop != Object.class);
    }
}

其他回答

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

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)

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

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

@Jon Skeet解释得好。 在我看来,如果有人想打电话给管理员。超方法则必须是想要忽略直接父元素的行为,但想要访问大父元素的行为。 这可以通过实例Of来实现。如下代码

public class A {
    protected void printClass() {
        System.out.println("In A Class");
    }
}

public class B extends A {

    @Override
    protected void printClass() {
        if (!(this instanceof C)) {
            System.out.println("In B Class");
        }
        super.printClass();
    }
}

public class C extends B {
    @Override
    protected void printClass() {
        System.out.println("In C Class");
        super.printClass();
    }
}

这是驾驶员课,

public class Driver {
    public static void main(String[] args) {
        C c = new C();
        c.printClass();
    }
}

它的输出将是

In C Class
In A Class

在这种情况下,类B printClass行为将被忽略。 我不确定这是一个理想的或好的做法,以达到超级。非常好,但它仍然有效。

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

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

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

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

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

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