为什么我们不能用私有扩展类方法重写基类方法?
class One {
void foo() { }
}
class Two extends One {
private void foo() { /* more code here */ }
}
为什么上面的代码片段是错误的?
class One {
void foo() { }
}
class Two extends One {
private void foo() { /* more code here */ }
}
Why is the above snippet of code wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我将尝试结合其他答案的想法来得出一个答案。
首先,让我们看一下代码中发生了什么。
看一下代码
One
类有一个包私有的foo
方法:Two
类是One
类,并且foo
方法被重写,但具有访问修饰符private
。问题
Java 语言不允许子类降低子类中方法、字段或类的可见性,因此,
Two
类降低了>foo
方法不合法。为什么降低可见性是一个问题?
考虑一下我们想要使用
One
类的情况:在这里,调用
foo
方法>一个实例有效。 (假设AnotherClass
类与One
类位于同一个包中。)现在,如果我们要实例化
Two
对象并将其放入One
类型的obj
变量中吗?Two.foo
方法是私有的,但是One.foo
方法将允许访问该方法。我们这里有问题。因此,在考虑继承时允许降低可见性没有多大意义。
链接
I'm going to try to incorporate the ideas from the other answers to come up with a single answer.
First off, let's take a look at what's going on in the code.
A look at the code
The
One
class has a package-privatefoo
method:The
Two
class which subclasses theOne
class, and thefoo
method is overriden, but has the access modifierprivate
.The issue
The Java language does not allow subclasses to reduce the visibility of a method, field or class in a subclass, therefore, the
Two
class reducing the visibility of thefoo
method is not legal.Why is reducing visibility a problem?
Consider the case where we want to use the
One
class:Here, calling the
foo
method on theOne
instance is valid. (Assuming that theAnotherClass
class is in the same package as theOne
class.)Now, what if we were to instantiate the
Two
object and place it in theobj
variable of the typeOne
?The
Two.foo
method is private, yet, theOne.foo
method would allow the access to the method. We've got a problem here.Therefore, it doesn't make much sense to allow reduction of visibility when taking inheritance into account.
Links
这段代码的问题是,如果它是合法的,如果您通过
One 间接访问它,Java 将无法尊重
foo
的private
修饰符基类。例如,如果我写Then 我们就会遇到麻烦,因为我们会间接调用
Two
的private
方法foo
,因为当编译器检查obj.foo()
行时,它会查看One
来确定foo
是否可访问,而不是查看Two
。原因是编译器不能总是知道 obj 可能指向什么 - 例如,如果我写了类似的内容那么编译器无法知道 obj 是否指向code> 指向
One
或Two
。因此,在检查访问说明符时它遵循One
。如果我们确实被允许在Two
中将foo
标记为私有,那么编译器将错误地允许我们通过obj
调用它,其类型为 < code>One,绕过了只有对象本身才能调用private
方法的保证。The problem with this code is that if it were legal, Java wouldn't be able to respect the
private
modifier offoo
if you accessed it indirectly through theOne
base class. For example, if I were to writeThen we'd be in trouble because we'd be calling the
private
methodfoo
ofTwo
indirectly, since when the compiler checks the lineobj.foo()
it looks atOne
to determine iffoo
is accessible, not atTwo
. The reason for this is that the compiler can't always tell whatobj
could be pointing at - if, for example, I write something likeThen the compiler can't know whether
obj
points at aOne
or aTwo
. Consequently, it defers toOne
when checking access specifiers. If we were indeed allowed to markfoo
private inTwo
, then the compiler would incorrectly allow us to call it throughobj
, which has typeOne
, bypassing the guarantee that only the object itself can callprivate
methods.给出的答案为您提供了为什么不能将一乘二扩展的技术解释。我想让您理解为什么这是不可能的,因为面向对象的模式而不是语言本身。
通常,类 One 是一个类的一般定义,及其对外部世界的访问器、方法。扩展此类的子类必须向外部世界提供相同的访问器。在您的示例中,二扩展了一,这意味着二提供了与一一样的外部世界访问器。如果您要更改 One 访问器的可见性,外部世界将无法再访问您的类,因为它们用于对类型 One 的对象执行此操作。
The given answers give you the technical explanation why you cannot extend One by Two. I would like to give you an understanding why this is not possible due to the object oriented pattern and not because of the language itself.
Usually the class One is a general definition of a class with its accessors, the methods, to the outer world. Sublcasses which extend this class must provide the same accessors to the outer world. Two extends One in your example, what means, that Two provides the same accessors to the outer world like One does. If you would change the visibility of the accessors of One, the outer world could no longer access your class as they are used to do it with an object of type One.
它会破坏多态性。
如果您有一个 Two 实例存储在 Two 变量中,那么 foo 无法被调用是有道理的。但是,如果将 Two 实例存储在 One 变量中,则您只知道 One。但是 One 有一个公共 foo,可以调用它。这会是一种不一致,而且会很奇怪。
It would break polymorphism.
If you have a Two instance stored in a Two variable, then it would make sense that foo cannot be called. But if you store a Two instance in a One variable, you only know about One. But One's have a public foo, and that can be called. This would be an inconsistency and would be really weird.
因为继承是一种是关系。任何人都可以通过对
One
的引用来引用Two
的实例:如果您在 v 引用上调用 foo 方法,程序会做什么?您破坏了 One 的公共契约,该契约保证 One 的每个实例都有一个(此处受包保护的)foo 方法。这就是编译器禁止它的原因。
Because inheritance is a is a relationship. Anyone could refer to a instance of
Two
through a reference toOne
:What would the program do if you called the foo method on the v reference? You broke the public contract of One, which guarantees that every instance of One has a (here package-protected) foo method. That's why the compiler forbids it.