为啥 Kotlin 类默认是 final 而不是 open?
Posted
技术标签:
【中文标题】为啥 Kotlin 类默认是 final 而不是 open?【英文标题】:Why are Kotlin classes final by default instead of open?为什么 Kotlin 类默认是 final 而不是 open? 【发布时间】:2019-01-11 18:47:18 【问题描述】:文档告诉我们关于open
注解的以下内容:
类上的 open 注解与 Java 的 final 相反:它 允许其他人从这个类继承。默认情况下,所有类 Kotlin 是final,对应Effective Java, 3rd Edition, 第 19 条:设计和记录继承或禁止继承。
我的课
class Foo //I can't inherit it
open class Bar //I can inherit it
默认保留所有类final
的真正动机是什么?性能有什么提升吗?还是只是一种设计模式?为什么默认禁止open
?
【问题讨论】:
您应该阅读 Effective Java 项目。它描述了为继承设计一个类需要多少工作。 极度痛苦的工作量。记录您对子类的所有要求,以及您要求他们不要做的所有事情。构建至少 3 个单独的子类,以验证您的基类实际上是有用的(哦,您不能自己编写这些类;必须由其他人编写,因为您会作弊)。等等等等等等。 大多数类应该是最终的。扩展它们可能是个坏主意。 【参考方案1】:对我来说有两个原因:
首先,Kotlin 从函数式编程世界中汲取了许多想法,并尽可能频繁地使用不变性来避免所有 known problems with mutation。
因此,默认情况下将每个类声明为“final”(至少对我而言)是相似的。
在运行时不能更改或更改类(使用反射之类的东西),这会使 Kotlin 编译器的安全检查无用。
所以如果你想“改变”一个类的默认实现,你必须明确地将它标记为打开。
我想到的第二个想法是继承经常被误用。 一些常见陷阱的例子解释了here
有“Favor composition over inheritance”原则作为更好设计的指导方针。因此,默认情况下将每个类声明为 final 会迫使开发人员至少停下来思考解决问题的替代方法,而不是出于错误的原因使用继承。
但只要没有 kotlin 开发者的官方声明,我只能给出一个固执己见的答案。
【讨论】:
【参考方案2】:Kotlin 设计师只是想确保每个人都遵循良好的做法。
正如已经记录的那样,设计师遵循Joshua Bloch's Effective Java,其中在类和接口一章中谈到了其中一个原则
设计和记录继承或禁止它
它提倡在使用之前明确记录任何继承行为的想法。
假设我们有,
class Foo
我们(即使是此代码的非作者) 确信此 class Foo
对任何扩展都是关闭的,并且没有随机类正在使用它,这也是通过查看它的签名。相比之下,Java
类则不能这样说,除非声明为 final
,否则某些悬空子类仍然可以扩展它。
另一方面,
open class Foo
仅通过类签名,我们就知道这个类是开放的继承,并且可能有多个类覆盖它的行为。如您所见,此处明确记录了继承。
【讨论】:
如果你是 S.O.L.I.D.人,这似乎是在面对Open for Extension的飞行。我发现期末课程非常令人沮丧,尤其是在图书馆中。如果存在错误或者您想扩展它们,这会使过程变得非常复杂。编写良好的库具有内置的可扩展性,但没有人知道未来会怎样或如何使用库。【参考方案3】:在默认情况下使类 final 可以在运行时使用更少的内存。
【讨论】:
【参考方案4】:我能想到的另一个原因是 final 使静态调度优化成为可能,这意味着它不需要进行方法表查找。
【讨论】:
以上是关于为啥 Kotlin 类默认是 final 而不是 open?的主要内容,如果未能解决你的问题,请参考以下文章
JAVA,为啥final类不能被继承,如果定义为final的类该类里面成员变量不特殊说明则是final类还是非final
在Kotlin上怎样用Mockito2 mock final 类(KAD 23)
为啥使用 NSError 间接参数而不是 @try/@catch/@finally