我理解制作类sealed
/ final
的单个方法的动机,但完全禁止从类继承的目的是什么?虽然允许覆盖某些方法可能导致不良事件发生,但我无法看到如何允许从类中继承纯粹为了在不覆盖现有行为的情况下向其添加行为可能是一件坏事。如果你真的想要禁止在你的类中覆盖任何东西,为什么不只是让每个方法都最终但仍然允许继承以便添加行为?
答案 0 :(得分:4)
在“为什么字符串是最终的Java”问题中有一些很好的讨论:Why is String class declared final in Java?
在这种情况下的基本摘要是,String是不可变的,如果它可以是子类,子类可能使它变为可变。
答案 1 :(得分:3)
更一般地说,可以将类设为final,以便保留使其工作的不变量。我强烈推荐Joshua Bloch的“Effective Java”,以便就此问题和相关问题进行讨论。
答案 2 :(得分:3)
组织/软件开发团队可能希望强制执行某些编码标准。例如,为了提高可读性,他们可能只希望使用方法Z修改类Y的属性X而不是其他任何东西。如果类不是最终的,那么一些开发人员可能会扩展类Y并添加方法W,这可能会以不同的方式修改X,并在理解所编写的代码时引起混淆和延迟。
答案 3 :(得分:2)
以这种方式思考:您花了最近3个月的时间为自己的框架开发基础类,其他人将要使用,并且框架的整体一致性基于此类中编写的代码,修改此class可能会导致框架的错误,错误和错误行为,你如何阻止优秀的程序员扩展它并覆盖其中一种方法?
除此之外,还有一些应该是不可变的类,例如Java中的java.lang.String类,扩展它并改变它的行为可能会造成很大的混乱!
最后,有时将类或方法设置为final会提高性能,但我从未对其进行过测试,也没有看到任何理由让一个类/方法最终得到一个非常微小的性能增益,等于零与在该计划中完成其他工作所需的时间相比。
答案 4 :(得分:0)
我认为这取决于。
如果我有内部应用程序,默认情况下我不会在类级别使用final。代码太乱了。在某些情况下,如果我想安全地重构,最终修饰符甚至会非常烦人(参见programming by difference术语)。在某些情况下,当我试图重构时,'默认最终狂热'会产生很大的问题。
另一方面,如果我设计一个代码更加扩展驱动的api / framework,我会更积极地使用final来实现类。这里错误的扩展可能是一个大问题,'final'修饰符是避免此类编程错误的安全方法。
但我只是反对默认使用'final'像许多人一样。它具有更多的缺点作为优点。对我来说,默认设置应该是'明智且更常见的设置'。
答案 5 :(得分:0)
据我所知,这是关于maintining invariants。
在类似的情况下,例如,您可以公开您的属性,但之后您将失去对其值的控制权,因为客户端可以直接更改它们,破坏您想要维护的某些属性。因此,以同样的方式禁止客户端直接访问某些(大多数实际)字段以保持一些不变量,您也可以使您的类/方法最终保持一些不变量。
我看到的一个常见例子与不变性有关,如果一个类不是最终的,那么可以破坏它。
当用户扩展一个类并仅在他的系统中使用它时,问题并非真正存在,与他自己的“混乱”生活在一起。真正的问题与class / methods / attributes / objects / ...不存在孤立的事实有关。
假设你有一个类CC1的集合,它们可以实现某个目标,其中一个类CC1_A应该“生成”只有不可变对象(或者你想要的任何其他不变量)。然后继续扩展CC1_A,使CC2_AX(在第二个类集合中扩展A)。你现在可以做的是使用CC1的东西通过一个需要CC1_A的CC2_AX。但是,CC1的构建假设CC1_A对象是不可变的,但是你的CC2_AX对象不是(假设它们不仅仅是为了示例)。这可能会导致程序出现严重问题。这样的问题甚至可以在课堂内部发生。例如,CC1_A的方法可能会假设CC1_A对象是不可变的,因此来自CC1_A的CC2_AX方法可能会失败,因为CC2_AX打破了不变性属性。
在我们的系统中,今天,我们有许多课程,而且我们所做的很多内容都是隐含的。所以我们并不总是想到我们想要保持的不变量。这不会让事情变得更容易。
顺便说一下,其他一些不变量包括:
它一直在继续。有些类只是因为它们保持更强的不变量(例如,使用特定的算法)而有用,并且扩展允许人们容易地破坏那种东西。而这一切都是一个问题的原因与这些不孤立的事情有关。