kotlin - 为什么密封类的私有构造函数可以在子类中调用?
问题描述
Kotlin 中的密封类只能有private
构造函数。这意味着我们只能调用构造函数本身:
密封类不允许有非私有的构造函数(它们的构造函数默认是私有的)。
// `private` and `constructor()` are redundant.
sealed class Expr private constructor()
但是,当我们使用密封类时,子类必须继承密封类:
// Above Kotlin 1.1
data class Const(val number: Double) : Expr()
data class Sum(val e1: Expr, val e2: Expr) : Expr()
正如您在上面的代码中看到的,密封类的private
构造函数是在密封类本身之外调用的。子类实例化时,先调用父类(密封类)的构造函数,再调用子类自己的构造函数。它只是可见性修饰符的例外吗?
https://kotlinlang.org/docs/reference/visibility-modifiers.html#classes-and-interfaces
对于在类内声明的成员:
private
表示仅在该类内可见(包括其所有成员);
解决方案
考虑以下代码:
open class A private constructor(var name: String){
class B : A("B")
class C : A("C")
}
上面的代码编译得很好,因为构造函数是在类 A 内部调用的。如果类 D 试图从 A 外部继承,它将无法编译。
class D : A("D") // Error: Cannot access '<init>': it is private in 'A'
正如在 Kotlin 中的 Sealed 类页面中提到的,
密封类可以有子类,但所有子类都必须在与密封类本身相同的文件中声明。(在 Kotlin 1.1 之前,规则更加严格:类必须嵌套在密封类的声明中)。
似乎 kotlin 只放宽了嵌套类的要求。
因此,以下代码在 1.1+ 中可以正常工作,但在早期版本中会失败:
sealed class A(var name: String)
class B : A("B")
class C : A("C")
而在 1.1 之前的版本中将需要以下代码,它尊重私有构造函数。
sealed class A (var name: String){
class B : A("B")
class C : A("C")
}
因此,允许在类之外(但在同一个文件中)密封类的私有构造函数可以被认为是使代码更清晰的增强。
推荐阅读
- php - 使用 google drive api v3 复制文件返回“提供的文件 ID 不可用。”
- java - 为什么强迫人们编译/构建 JAR 文件而不是仅仅托管 JAR 文件本身?
- iis - ASP.NET CORE 5.0 Web API 在 IIS Express 上工作,但在 IIS 10 上托管时提供 404
- apache-spark - 通过从另一列解析字符串来创建列
- python-3.x - 将 selenium 与 2captcha 集成以解决 Recapv2
- go - 方法执行期间内存消耗高
- wordpress - 是否可以使用 Go 将现有的 CRD 添加到自定义 Kubernetes 运算符中?
- php - 用phpredis连接Redis,耗时20ms
- c++ - 链接两个独立的 cmake 项目,其中一个依赖于另一个
- python - 在 Web 服务器中时无法从 Python 打印(到打印机)