为什么会出现在OOP类的选项被标记,以从来没有从祖先继承?(Why there is an opti

2019-09-23 00:40发布

“密封”关键字在C#中,最后在Java中。

正如我几乎从来没有产生任何图,我只用已经完成(从框架)班我还是后几年不知道为什么会有人“锁定”一类,所以它永远不会被扩展/继承。

它是有益的? 有没有做是可能从继承扩展扔掉,以“封其为”可能性的所有类的任何伤害?

对不起,请问这在2012年,其中OOP是微不足道的,但我希望得到一个很好的解释和/或良好来源的阅读! 因为对我来说是没用的,我不能相信这仅仅是一个简单的概念。

但是我到处寻找答案都是一样的:“标记一个类防止它从别人继承。”

Answer 1:

  1. 安全性 -继承类可能访问的基类的内部零件,打破封装

  2. 合约 -继承类有可能打破由基类提供的合同。 见里氏替换原则

  3. 不变性 - 2的特殊情况-继承类可以引入可变字段不变类

  4. 性能 -虚拟机可以积极优化这样的类,例如,假设方法永远不会覆盖,避免虚呼叫

  5. 简单 -实施方法,如equals()要简单得多,而不会打扰关于继承



Answer 2:

原因是,如果允许子类,并把没有限制哪个方法子类可以重写,更新到基类,保留行为仍然可以打破的子类。 换句话说,这是不安全的来自不是专门设计成可扩展的一个类继承(通过指定特定的方法作为可重写的,使所有其它final )。这就是所谓的脆基类问题-见本文中的示例,而本文对这一问题的更透彻的分析。

如果基类没有被设计为继承,这是一个公共的API(可能是库)的一部分,现在你遇到了大麻烦。 你有过谁的子类代码没有控制权,你有没有办法知道是否改变将是子类安全只是看着基类的方法。 底线是,你要么设计无限继承或者完全禁止它。


请注意,它可能有子类的数量有限 。 这可以用私有构造和内部类实现:

class Base {
    private Base() {}

    (public|private) static final class SubA extends Base { ... }
    (public|private) static final class SubB extends Base { ... }
    (public|private) static final class SubC extends Base { ... }
}

该内部类可以访问私有的构造函数,但顶级类没有,所以你只能从里面继承它。 这可以让你表达的概念,即“型底座的值可以是苏巴或SUBB或SUBC”。 这里没有危险,因为基地将通常是空的(你没有真正继承自基地的任何东西),所有的子类是你的控制之下。

你可能会认为这是一个代码味道,因为你已经知道该类型的子类的。 但是,你应该认识到,实现抽象的这种替代方法是对接口互补。 当你有子类的有限数量的,可以很容易地增加新的功能(处理子类固定数量的),但很难增加新类型(每个现有方法需要更新,以应付新的子类)。 当你使用一个接口或允许无限的子类,可以很容易地添加新类型(实现的方法固定数量的),但它很难添加新的方法(你需要更新每一个类)。 一个人的力量是对方的弱点。 有关主题的详细论述,请参阅的了解数据抽象,再探 。 编辑:我的错误; 本文我联系一个不同的二重性(ADT的VS对象/接口)会谈。 我其实想的是表达的问题 。


有不太严重的原因,以避免继承为好。 假设你开始了与A类,然后实现在子类中乙了一些新的功能,以及后来在子类中添加其他功能。然后你意识到你需要这两种功能,但不能创建一个子类BC扩展B和C.即使你设计的继承和防止脆弱的基类问题有可能得到这个咬伤。 除了我上面显示的模式, 继承的大多数使用与成分更好地被替换 -例如,使用策略模式 (或简单地使用高阶的功能,如果你的语言支持的话)。



文章来源: Why there is an option for a class in OOP be marked to never inherit from ancestral?