Kotlin 中的密封类只能有private构造函数。这意味着我们只能调用构造函数本身:
密封类不允许有非私有构造函数(它们的构造函数默认是私有的)。
// `private` and `constructor()` are redundant.
sealed class Expr private constructor()
Run Code Online (Sandbox Code Playgroud)
但是,当我们使用密封类时,子类必须继承密封类:
// Above Kotlin 1.1
data class Const(val number: Double) : Expr()
data class Sum(val e1: Expr, val e2: Expr) : Expr()
Run Code Online (Sandbox Code Playgroud)
正如您在上面的代码中看到的那样,密封类的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")
}
Run Code Online (Sandbox Code Playgroud)
上面的代码编译得很好,因为构造函数是在类 A 内部调用的。如果类 D 尝试继承 A 外部,它将无法编译。
class D : A("D") // Error: Cannot access '<init>': it is private in 'A'
Run Code Online (Sandbox Code Playgroud)
正如Kotlin 中的 Sealed class页上提到的,
密封类可以有子类,但所有子类都必须在与密封类本身相同的文件中声明。(在 Kotlin 1.1 之前,规则更加严格:类必须嵌套在密封类的声明中)。
看来kotlin只放宽了嵌套类的要求。
因此,以下代码在 1.1+ 中工作正常,但在早期版本中会失败:
sealed class A(var name: String)
class B : A("B")
class C : A("C")
Run Code Online (Sandbox Code Playgroud)
而在 1.1 之前的版本中需要以下代码,它尊重私有构造函数。
sealed class A (var name: String){
class B : A("B")
class C : A("C")
}
Run Code Online (Sandbox Code Playgroud)
因此,允许类外部(但在同一文件内)密封类的私有构造函数可以被认为是一种增强功能,可以使代码更简洁。
| 归档时间: |
|
| 查看次数: |
3327 次 |
| 最近记录: |