设计模式为什么Java允许增加子类中受保护方法的可见性?
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允许增加可见性,那么有两种方法是公开可见的
我知道界面是一种解决方案,但还有其他解决办法吗
# 1 楼答案
其他响应中已经解释了为什么不允许降低可见性(这将破坏父类的契约)
但是为什么允许它增加方法的可见性呢?首先,它不会违反任何合同,因此没有理由不允许它。当一个方法在子类中不受保护是有意义的时候,它有时会很方便
其次,不允许这样做可能会产生副作用,即有时无法扩展类并同时实现接口:
关于你的第二个问题,你无能为力。您必须相信实现子类的人不会做任何破坏您的实现的事情。即使java不允许增加可见性,也无法解决您的问题,因为可以创建一个具有不同名称的公共方法来调用抽象方法:
# 2 楼答案
假设有可能降低能见度。然后查看以下代码:
假设您在另一个包中有另一个类,您在其中使用这些类:
为了检查是否允许方法调用,编译器会查看调用它的变量的类型。变量
a
的类型是Super
。但是a
引用的实际对象是一个Sub
,并且那里的方法是protected
,因此您可以说不允许它从包外的无关类调用该方法。为了解决这种奇怪的情况,禁止使重写的方法变得不可见请注意,另一种方法(使方法更可见)不会导致相同的问题
# 3 楼答案
因为Java允许超类引用指向子类对象。。因此,限制不应该从
compile-time
增加到runtime
让我们通过一个例子来了解这一点:-
现在,创建类
A
的对象,并为其分配类B
的引用。。 让我们看看如何:现在,由于
compiler
只检查引用变量的类型,并检查该类(类B)中方法的可见性,而它不检查reference
obj引用的对象是什么类型的。。所以,它并不担心。。由JVM在运行时解析适当的方法但是在运行时,JVM实际上会尝试调用类
meth
的A
方法,因为对象是类A的。。但是,现在发生了什么BOOOOOMM--->;JVM崩溃。。因为meth
方法在class A
中是私有的这就是为什么不允许降低能见度
# 4 楼答案
如果基类做出关于可见性的承诺,那么子类就不能违背该承诺并且仍然满足Liskov替换原则。在任何情况下都不能使用子类,如果承诺被破坏,那么承诺的方法就会被暴露
子类是一个基类。如果基类公开方法,那么子类也必须公开方法