繁体   English   中英

为什么我们不能用私有扩展类方法覆盖基类方法?

[英]Why can’t we override a base class method with private extended class method?

class One {
    void foo() { }
}
class Two extends One {
    private void foo() { /* more code here */ }
}

为什么上面的代码片段是错误的?

我将尝试结合其他答案中的想法来得出一个答案。

首先,让我们看看代码中发生了什么。

看一下代码

One类有一个包私有的foo方法:

class One {
    // The lack of an access modifier means the method is package-private.
    void foo() { }
}

Two类是One类的子类, foo方法被覆盖,但具有访问修饰符private

class Two extends One {
    // The "private" modifier is added in this class.
    private void foo() { /* more code here */ }
}

问题

Java 语言不允许子类降低子类中方法、字段或类的可见性,因此,降低foo方法可见性的Two类是不合法的。

为什么降低能见度是一个问题?

考虑我们要使用One类的情况:

class AnotherClass {
  public void someMethod() {
     One obj = new One();
     obj.foo();  // This is perfectly valid.
  }
}

在这里,在One实例上调用foo方法是有效的。 (假设AnotherClass类与One类在同一个包中。)

现在,如果我们要实例化Two对象并将其放在One类型的obj变量中呢?

class AnotherClass {
  public void someMethod() {
     One obj = new Two();
     obj.foo();  // Wait a second, here...
  }
}

Two.foo方法是私有的,但是One.foo方法允许访问该方法。 我们这里有问题。

因此,在考虑继承时允许降低可见性没有多大意义。

链接

这段代码的问题在于,如果它是合法的,那么如果您通过One基类间接访问它,Java 将无法尊重fooprivate修饰符。 例如,如果我要写

One obj = new Two();
obj.foo();

然后我们会遇到麻烦,因为我们将间接调用Twoprivate方法foo ,因为当编译器检查obj.foo()它会查看One以确定foo是否可访问,而不是在Two 这样做的原因是编译器不能总是告诉obj可能指向什么 - 例如,如果我写了类似的东西

One obj = Math.random() < 0.5? new One() : new Two();
obj.foo();

那么编译器就无法知道obj指向One还是指向Two 因此,它在检查访问说明符时遵循One 如果我们确实被允许在Two标记foo private ,那么编译器会错误地允许我们通过obj调用它,它的类型为One ,绕过只有对象本身可以调用private方法的保证。

给出的答案为您提供了为什么不能一一扩展的技术解释。 我想让你理解为什么这是不可能的,因为面向对象模式而不是因为语言本身。

通常,类 One 是一个类的一般定义,它带有外部世界的访问器、方法。 扩展此类的子类必须为外部世界提供相同的访问器。 在您的示例中,两个扩展了一个,这意味着两个为外部世界提供了与 One 相同的访问器。 如果您要更改 One 访问器的可见性,外部世界将无法再访问您的类,因为它们习惯于对类型为 One 的对象进行访问。

它会破坏多态性。

如果你有一个 Two 实例存储在 Two 变量中,那么不能调用 foo 是有道理的。 但是,如果将 Two 实例存储在 One 变量中,则您只知道 One。 但是 One 有一个公共 foo,可以调用它。 这将是不一致的,并且真的很奇怪。

因为继承是一种关系。 任何人都可以通过引用One来引用Two的实例:

One v = new Two();

如果你在 v 引用上调用 foo 方法,程序会做什么? 你破坏了 One 的公共契约,它保证 One 的每个实例都有一个(这里是包保护的)foo 方法。 这就是编译器禁止它的原因。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM