Nar*_*hai 16 java design-patterns
abstract class Base{
protected abstract void a();
}
class Child extends Base{
@Override
public void a(){
//why is this valid
}
}
Run Code Online (Sandbox Code Playgroud)
为什么我们不能降低能见度但可以增加它?
此外,我需要实现模板模式,其中公共方法可见只能是基类.
例:
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
}
}
Run Code Online (Sandbox Code Playgroud)
现在,如果java允许增加可见性,那么有两种方法可以公开显示?
我知道接口是一个解决方案但是还有其他方法吗?
Pab*_*blo 26
为什么不允许降低可见性已在其他响应中解释(它将破坏父类的合同).
但为什么允许增加方法的可见性?首先,它不会破坏任何合同,因此没有理由不允许它.有时,它可以很方便,当在子类中有意义的方法不受保护时.
其次,不允许它可能会产生副作用,有时无法扩展类并同时实现接口:
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.
}
Run Code Online (Sandbox Code Playgroud)
关于你的第二个问题,你无能为力.您必须相信实现子类的人不会做任何破坏您的实现的事情.即使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.
}
}
Run Code Online (Sandbox Code Playgroud)
duf*_*ymo 13
如果基类对可见性做出承诺,那么子类不能破坏该承诺并仍然满足Liskov替换原则.如果承诺被破坏,则在承诺方法暴露的任何情况下都不能使用子类.
子类IS-A基类.如果基类公开了一个方法,那么子类也必须公开.
在Java或C++中没有出路.我猜在C#中也是如此.
为什么我们不能降低能见度但可以增加它?
假设有可能降低能见度。然后看下面的代码:
class Super {
public void method() {
// ...
}
}
class Sub extends Super {
@Override
protected void method() {
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
假设您将在另一个包中拥有另一个类,您将在其中使用这些类:
Super a = new Sub();
// Should this be allowed or not?
a.method();
Run Code Online (Sandbox Code Playgroud)
要检查是否允许方法调用,编译器会查看调用它的变量的类型。变量的类型a是Super。但是a引用的实际对象是 a Sub,并且方法是protected,因此您会说不应该允许从包外的不相关类调用该方法。为了解决这种奇怪的情况,禁止使覆盖的方法不那么可见。
请注意,反过来(使方法更加可见)不会导致相同的问题。