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

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

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

你们怎么看?

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


当前回答

public class SubSubClass extends SubClass {

    @Override
    public void print() {
        super.superPrint();
    }

    public static void main(String[] args) {
        new SubSubClass().print();
    }
}

class SuperClass {

    public void print() {
        System.out.println("Printed in the GrandDad");
    }
}

class SubClass extends SuperClass {

    public void superPrint() {
        super.print();
    }
}

输出:打印在祖父

其他回答

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

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

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

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

我会把超级。如果可能的话,超级方法主体放在另一个方法中

class SuperSuperClass {
    public String toString() {
        return DescribeMe();
    }

    protected String DescribeMe() {
        return "I am super super";
    }
}

class SuperClass extends SuperSuperClass {
    public String toString() {
        return "I am super";
    }
}

class ChildClass extends SuperClass {
    public String toString() {
        return DescribeMe();
    }
}

或者如果你不能改变超超类,你可以试试这个:

class SuperSuperClass {
    public String toString() {
        return "I am super super";
    }
}

class SuperClass extends SuperSuperClass {
    public String toString() {
        return DescribeMe(super.toString());
    }

    protected String DescribeMe(string fromSuper) {
        return "I am super";
    }
}

class ChildClass extends SuperClass {
    protected String DescribeMe(string fromSuper) {
        return fromSuper;
    }
}

在这两种情况下,

new ChildClass().toString();

结果变成“我超级超级”

我认为以下代码允许在大多数情况下使用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);
    }
}

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

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

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

这很容易做到。例如:

B的C子类和a的B子类,这三个都有方法methodName()。

public abstract class A {

    public void methodName() {
        System.out.println("Class A");
    }

}

public class B extends A {

    public void methodName() {
        super.methodName();
        System.out.println("Class B");
    }

    // Will call the super methodName
    public void hackSuper() {
        super.methodName();
    }

}

public class C extends B {

    public static void main(String[] args) {
        A a = new C();
        a.methodName();
    }

    @Override
    public void methodName() {
        /*super.methodName();*/
        hackSuper();
        System.out.println("Class C");
    }

}

运行类C输出如下: A类 C类

而不是输出: A类 B类 C类