问题描述
abstract class Base{ protected abstract void a(); } class Child extends Base{ @Override public void a(){ //why is this valid } }
为什么我们不能降低可见度,但可以提高知名度?
我还需要实现模板模式,公共方法可见只能是基类.
示例:
abstract class Base{ public void callA(){ //do some important stuff a(); } protected abstract void a(); } class Child extends Base{ @Override public void a(){ //why is this valid } }
现在,如果Java允许提高可见度,则可以公开可见两种方法?
我知道接口是一种解决方案,但是还有其他方法吗?
推荐答案
为什么在其他答复中已经解释了为什么不允许可见性降低(这将破坏父类的合同).
但是为什么允许它提高方法的可见性?首先,它不会违反任何合同,因此没有理由不允许它.有时可能会方便,当在儿童课上有意义的方法不受保护时.
第二,不允许它具有不可能有时不可能的副作用,有时会扩展类并同时实现界面:
interface Interface1 { public void method(); } public class Parent { protected abstract void method(); } public class Child extends Parent implements Interface1 { @Override public void method() { } //This would be impossible if the visibility of method() in class Parent could not be increased. }
关于您的第二个问题,您无能为力.您必须相信,实施儿童班的人不会做任何破坏您实施的人.即使Java不允许提高可见性,这仍然无法解决您的问题,因为可以创建具有不同名称的公共方法来调用抽象方法:
class Child extends Base{ @Override protected void a(){ } public void a2() { a(); //This would have the same problems that allowing to increase the visibility. } }
其他推荐答案
如果基类对可见性做出承诺,那么子类将无法打破该诺言并仍然满足Liskov替代原则.如果该承诺被损坏,则不能在任何情况下使用承诺方法的任何子类.
子类IS-A基类.如果基类公开了一种方法,则子类也必须.
Java或C ++没有出路.我想在C#中也是如此.
其他推荐答案
为什么我们不能降低可见度,但可以提高知名度?
假设可以降低可见度.然后查看以下代码:
class Super { public void method() { // ... } } class Sub extends Super { @Override protected void method() { // ... } }
假设您将在另一个包中使用另一个类,其中您使用这些类:
Super a = new Sub(); // Should this be allowed or not? a.method();
要检查是否允许使用方法调用,编译器查看您称之为变量的类型.变量a的类型为Super.但是a指的是Sub,并且该方法为protected,因此您不应允许它从包装外部的无关类调用该方法.为了解决这种奇怪的情况,它被禁止使被覆盖的方法降低.
请注意,另一种方式(使方法更可见)不会导致同样的问题.
问题描述
abstract class Base{ protected abstract void a(); } class Child extends Base{ @Override public void a(){ //why is this valid } }
Why is that we can't reduce the visibility but can increase it?
Also I need to implement Template pattern in which the public methods visible can only be of base class.
Example:
abstract class Base{ public void callA(){ //do some important stuff a(); } protected abstract void a(); } class Child extends Base{ @Override public void a(){ //why is this valid } }
Now if java allows to increase visibility then there are two methods visible publicly??
I know interface is one solution but is there some other way out???
推荐答案
Why decreasing visibility is not allowed is already explained in other responses (it would break the contract of the parent class).
But why it is allowed to increase the visibility of a method? First, it would not break any contract, so there is no reason to not allow it. It can be handy sometimes, when it makes sense in the child class for a method to not be protected.
Second, not allowing it could have the side effect of making impossible sometimes to extend a class and implement an interface at the same time:
interface Interface1 { public void method(); } public class Parent { protected abstract void method(); } public class Child extends Parent implements Interface1 { @Override public void method() { } //This would be impossible if the visibility of method() in class Parent could not be increased. }
About your second question, you can do nothing about it. You have to trust that the person who implements the child class doesn't do anything that breaks your implementation. Even if java wouldn't allow to increase visibility, that would still not fix your problem, because a public method with a different name could be created that calls the abstract method:
class Child extends Base{ @Override protected void a(){ } public void a2() { a(); //This would have the same problems that allowing to increase the visibility. } }
其他推荐答案
If the base class makes a promise regarding visibility, then the subclass cannot break that promise and still satisfy the Liskov substitution principle. You can't use a subclass in any situation where the promised method is exposed if that promise is broken.
The subclass IS-A base class. If the base class exposes a method, so must the subclass.
There's no way out in Java or C++. I'd guess the same is true in C#.
其他推荐答案
Why is that we can't reduce the visibility but can increase it?
Suppose that it would be possible to reduce the visibility. Then look at the following code:
class Super { public void method() { // ... } } class Sub extends Super { @Override protected void method() { // ... } }
Suppose that you would have another class, in another package, where you use these classes:
Super a = new Sub(); // Should this be allowed or not? a.method();
To check whether a method call is allowed or not, the compiler looks at the type of the variable you call it on. The type of the variable a is Super. But the actual object that a refers to is a Sub, and there the method is protected, so you would say it should not be allowed to call the method from an unrelated class outside the package. To solve this strange situation, it's made forbidden to make overridden methods less visible.
Note that the other way around (making a method more visible) doesn't lead to the same problem.