人们说继承打破了封装,我同意这一点。他们说代表团更好 - 尽管代表团的修改者也可以公开/受到保护。
因为公共/受保护修饰符从超类暴露给扩展当前子类的任何新类的“连锁”效应,所以继承打破封装的真正原因是什么?
答案 0 :(得分:3)
是。因为它给派生类访问基类的成员(取决于什么语言和哪种继承),所以它打破了封装。恕我直言,只有你坚持最严格的封装。恕我直言,有理由说你接受派生类作为基础的扩展,因此以某种方式相关而不是真正打破封装。 纯粹主义者不同意这一点。
查看http://www.ccs.neu.edu/research/demeter/papers/context-journal/node17.html并搜索“休息”以获得学术解释。
答案 1 :(得分:1)
我认为从我的观点来看,它会在基类或超类中添加新方法时中断。如果A
是B
的子类,即使A
未以任何方式进行修改,B
中的更改也可能会中断A
。 (这称为涟漪效应)
示例:假设A
通过首先验证每种方法中的输入参数(出于安全原因)来覆盖B
中的所有方法。如果将新方法添加到B
并且A
未更新,则新的继承方法将引入安全漏洞。
为了摆脱继承中的陷阱,支持或使用“Composition”而不是继承,简单的聚合而不是继承,下面是一个例子:
想象一下,Person
和Employee
两个类。您可以在Employee
内撰写Person
并将Person
功能请求转发给撰写的类,而不是让Employee
继承Person
,我们仍然可以获得重用Person
类的好处。
备注:强>
Person
类可能是抽象类OR
Person
类可能与protected
Employee
答案 2 :(得分:0)
这取决于我们如何设计我们的类。在设计类时我们应该考虑Open-Closed原则。当我们讨论封装时,我们讨论的是修改,当我们谈论继承时,我们正在讨论扩展我们的应用程序然后我们作为设计者应该选择我们应该保护以防止修改(在我们的类中使用私有修饰符),从而封装我们的类以及为将来扩展保留的类的开放方面。(受保护的元素)。(可以把它看作.net语言中的部分概念,每个类可以分成不同的文件,因此其中一些可以由程序员扩展,而另一些则使用代码生成工具生成)
答案 3 :(得分:0)
想象:
class A {
void foo(){
...
this.bar();
...
}
void bar(){
...
}
}
class B extends A {
//override bar
void bar(){
...
}
}
class C {
void bazz(){
B b = new B();
// which bar would be called?
B.foo();
}
}
您在bazz
方法中看到哪个bar
将被调用?第二个将调用类B中的bar
。但是,这是什么问题呢?问题是类A中的foo
方法对类B中的bar
方法的覆盖一无所知,那么您的不变式可能会受到侵犯。因为foo可能期望bar方法的唯一行为是在自己的类中,所以不会覆盖某些内容。此问题称为脆弱的基类问题。