为什么是 super.super.method();在 Java 中不允许?

2022-08-31 04:38:28

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

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

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

你们怎么看?

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


答案 1

它违反了封装。您不应该绕过父类的行为。有时能够绕过你自己班级的行为(特别是从同一方法中),而不是你父母的行为,这是有意义的。例如,假设我们有一个基本的“项目集合”,一个表示“红色项目集合”的子类和一个表示“大红色项目集合”的子类。拥有:

public class Items
{
    public void add(Item item) { ... }
}

public class RedItems extends Items
{
    @Override
    public void add(Item item)
    {
        if (!item.isRed())
        {
            throw new NotRedItemException();
        }
        super.add(item);
    }
}

public class BigRedItems extends RedItems
{
    @Override
    public void add(Item item)
    {
        if (!item.isBig())
        {
            throw new NotBigItemException();
        }
        super.add(item);
    }
}

没关系 - RedItems 始终可以确信它包含的项目都是红色的。现在假设我们能够调用 super.super.add():

public class NaughtyItems extends RedItems
{
    @Override
    public void add(Item item)
    {
        // I don't care if it's red or not. Take that, RedItems!
        super.super.add(item);
    }
}

现在我们可以添加任何我们喜欢的东西,并且不变量被打破了。RedItems

这有意义吗?


答案 2

我认为Jon Skeet有正确的答案。我只想补充一点,您可以通过强制转换从超类的超类访问阴影变量:this

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)

但是,这不适用于方法调用,因为方法调用是根据对象的运行时类型确定的。


推荐