Oop 破坏继承的封装?

Oop 破坏继承的封装?,oop,encapsulation,access-modifiers,Oop,Encapsulation,Access Modifiers,人们说继承破坏了封装,我同意这一点。他们说委派更好——尽管委派中的修饰语也可以是公共的/受保护的 那么,继承破坏封装的真正原因是因为来自超类的公共/受保护修饰符的“连锁反应”效应被暴露给任何扩展当前子类的新类吗?是的。因为它让派生类访问基类的成员(取决于哪种语言和哪种继承),所以据说它破坏了封装。依我看,这只有在你坚持用最严格的术语来封装的情况下才行。可以合理地说,您接受派生类作为基类的扩展,因此在某种程度上是相关的,而不是真正破坏封装。 纯粹主义者不会同意这一点 查看并搜索“中断”以获得学术解

人们说继承破坏了封装,我同意这一点。他们说委派更好——尽管委派中的修饰语也可以是公共的/受保护的


那么,继承破坏封装的真正原因是因为来自超类的公共/受保护修饰符的“连锁反应”效应被暴露给任何扩展当前子类的新类吗?

是的。因为它让派生类访问基类的成员(取决于哪种语言和哪种继承),所以据说它破坏了封装。依我看,这只有在你坚持用最严格的术语来封装的情况下才行。可以合理地说,您接受派生类作为基类的扩展,因此在某种程度上是相关的,而不是真正破坏封装。 纯粹主义者不会同意这一点


查看并搜索“中断”以获得学术解释。

这取决于我们如何设计类。在设计类时,我们应该牢记原则。当我们谈论封装时,我们谈论的是修改,当我们谈论继承时,我们谈论的是扩展应用程序,作为设计者,我们应该选择我们应该保护哪些内容不被修改(在我们的类中使用私有修饰符),从而封装我们的类,以及为将来扩展保留的类的开放面(受保护的membmers)。(可以将其视为.net语言中的一个部分概念,即每个类可以分离为不同的文件,因此程序员可以扩展其中一些类,而其他一些类则使用代码生成工具生成)我认为,从我的角度来看,如果在基类或超类中添加新方法,它就会中断。如果
A
B
的子类,即使
A
没有任何修改,
B
中的更改也会中断
A
(这称为连锁反应)

示例:假设
A
通过首先验证每个方法中的输入参数来覆盖
B
中的所有方法(,出于安全原因)。如果向
B
添加新方法,并且
A
未更新,则新继承的方法将引入安全漏洞

要摆脱继承中的陷阱,请支持或使用“组合”而不是继承,使用简单聚合而不是继承,下面是一个示例:

设想两个类,
Person
Employee
。不要求
Employee
继承
Person
,您可以在
Employee
内部组合
Person
,并将对
Person
功能的请求转发给组合类,这样我们仍然可以获得重用
Person>的好处
class

注意事项:

  • Person
    类可能是抽象类或

  • 人员
    类可能与
    员工

想象一下:

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
方法的重写,那么您的不变量可能会被违反。因为se foo可能期望bar方法的唯一行为是在自己的类中,而不是被重写。这个问题称为脆弱基类问题

继承会破坏封装?只有在误用时……继承是面向对象设计的一个组成部分。继承不会破坏封装。派生类不会ot有权接触其基类的私人成员。“连锁反应”是OOP的一个组成部分;如果动物呼吸,那么狗、猫、人……也会呼吸。他们没有泄露动物的内在本质,只是意识到了这一点。谷歌搜索“继承vs委派”和“继承vs组合”在这个主题上产生了一些非常好的文章。不幸的是,我们不同意你问题的前提,这对我们来说是错误的。@Jon:请注意,你反对继承的论点几乎都适用于封装。假设有人可能错误地制作一个受保护的接口,从而破坏了封装隔离(通过固有),为什么你认为公共接口(通过委托)无法破坏封装?您的解决方案和您的前提一样有缺陷。继承不会破坏封装,即使是在纯粹的意义上。如果这些成员被封装并且无法从派生类访问,它们就不会是公共/受保护的。@MooingDuck看一下我回答中的链接。人们普遍认为我n继承打破了纯粹意义上的封装。“如果允许派生类访问从基类继承的成员,则基类中的更改也可能需要维护派生类。”如果允许实现更改通过接口泄漏,那么这不适用于任何类的任何使用者吗?我发现引用的源代码中的参数很弱。派生类只有在允许的情况下才能直接操作基类的数据(通过
protected
access修饰符)。如果你错误地将私有字段标记为受保护的,那么是你的设计被破坏了。@Douglas“破坏继承的封装”的学术论点是关于“受保护”的能力所有成员。仅仅是能够这样做的想法,即使是有意的,也是OOP纯粹主义者说继承破坏了封装的原因。但是超级类的设计者不能知道每一个可能扩展它的类?所以继承赋予的特权可能会被第六代/第七代子类滥用?你怎么看