据我所知,Substitution原则不允许子类具有访问权限较弱的字段,因为否则可能会破坏信息隐藏,并且还因为子类应始终提供与其至少相同的行为父母之一。对我来说很有意义。
但是同时我不明白扩展字段或方法访问级别的合理性吗?我在父班有一个私人领域,而在孩子班则是公共领域。您能举个例子说明为什么这样有意义吗?还是仅仅是出于设计选择?
答案 0 :(得分:1)
这不是您在私有字段中提到的那样。您不能将私有字段从超类扩展到子类。如果声明具有相同名称的字段,则为该子类定义一个新字段。
但是,您可以更改程序包的访问权限和受保护的访问权限,例如public之类,这不会造成任何问题,因为超类不为其子类提供该类,但是子类可能会根据其状态更改其行为,并希望为其他用户。
例如,在受保护的情况下,您只能在该程序包和子类中进行访问。但是,也许您在其中做了一些不利于公共实施的工作。 (如果将某些内容公开,则必须为将来的发行版提供支持),但是在子类中,您可能需要覆盖它并为其添加一些新功能,并提供可供其他人使用的结果。
一个很好的例子(java总是提供最好的例子):
如果看到的话,java在Object类中声明了这一点:
class Object {
protected native Object clone() throws CloneNotSupportedException;
}
所以没有人可以在上面拨打clone()
。很好,因为也许我不想在课堂上提供clone()
。但是,如果我愿意的话,可以很容易地覆盖它并使其对其他人公开,并在其中调用super.clone()
以供使用,该功能是在创建类的新副本之前实现的。不好吗?!
答案 1 :(得分:0)
它可能会违反信息隐藏
信息隐藏虽然是一种很好的做法,但与Liskov替换原则无关。
(A)子类应始终提供至少与其父类(类)相同的行为。
这是正确的,但是可以通过在继承的成员上禁止使用 stricter 访问修饰符来实现。 较弱访问修饰符会显示其他行为。
class A {
private int lastInput;
protected int getLastInput() {
return lastInput;
}
public int getSquareValue(int input) {
lastInput = input;
return getLastInput()*getLastInput();
}
}
class B extends A {
public int getLastInput() {
return super.getLastInput();
}
}
A aa = new A();
B bb = new B();
A ab = bb;
// All behaviors of A exist in B as well.
// B can be substituted for A.
System.out.println(aa.getSquareValue(5)); // 25
System.out.println(ab.getSquareValue(5)); // 25
// B also has new behaviors that A did not surface.
// This does not prevent B from substituting for A.
System.out.println(bb.getLastInput()); // 5
答案 2 :(得分:0)
https://docs.oracle.com/javase/tutorial/java/IandI/hidevariables.html
父级和子级有2个单独的测试实例。如您在本例中所见。
public class Main {
public class Parent{
private String test = "parent test";
String getTest() {
return test;
}
}
public class Child extends Parent {
public String test = "child test"; // defining it here hides the parent field
@Override
String getTest() {
return test;
}
}
public static void main(String[] args) {
Main main = new Main();
Parent parent = main.new Parent();
System.out.println(parent.getTest());
Child child = main.new Child();
System.out.println(child.getTest());
}
}
输出:
parent test
child test