如果我使用的是docs中的示例,
class SomeActivity : AppCompatActivity() {
sealed class Expr
data class Const(val number: Double) : Expr()
data class Sum(val e1: Expr, val e2: Expr) : Expr()
object NotANumber : Expr()
}
它无法编译,并显示错误:
Cannot access '<init>', it is private in 'Expr'.
但是,将其移到封闭类之外会使它编译:
sealed class Expr
data class Const(val number: Double) : Expr()
data class Sum(val e1: Expr, val e2: Expr) : Expr()
object NotANumber : Expr()
class SomeActivity : AppCompatActivity() {
}
为什么会这样?这是预期的行为吗?文档似乎没有提到这一点。
答案 0 :(得分:5)
是的,事实证明这是预期的行为。根据{{3}}:
建议:在同一文件中允许顶级子类用于顶级密封类。
对于非顶级密封类,应在其内部声明所有子类。因此,对于此类,什么也没有改变。
您想要的方案被列为一个悬而未决的问题。 the proposal allowing non-nested subclasses有一张票。目前似乎没有人对此进行研究。在讨论该提案时,开发人员说:
答案 1 :(得分:2)
从文档中:
密封类本身是抽象的,无法实例化 直接并且可以有抽象成员。
不允许封闭类具有非私有构造函数(它们的 构造函数默认是私有的。
我想您应该使用示例的方式如下:
fun main(args: Array<String>) {
val c = Const(5.0)
val s = Sum(Const(1.0), Const(3.0))
println(eval(c))
println(eval(s))
}
sealed class Expr
data class Const(val number: Double) : Expr()
data class Sum(val e1: Expr, val e2: Expr) : Expr()
object NotANumber : Expr()
fun eval(expr: Expr): Double = when(expr) {
is Const -> expr.number
is Sum -> eval(expr.e1) + eval(expr.e2)
NotANumber -> Double.NaN
// the `else` clause is not required because we've covered all the cases
}
答案 2 :(得分:1)
在Kotlin 1.0中,密封功能受到很大限制。对于 例如,所有子类都必须嵌套,并且不能将子类设为 数据类(本章后面将介绍数据类)。 Kotlin 1.1放松 限制,并允许您在以下任何位置定义密封类的子类 相同的文件。 在给定的示例中,到目前为止不允许这样做。可能是,在更高的发行版本中,他们将放宽此限制。 但是,您可以这样做:
`class SomeActivity {
sealed class Expr {
data class Const(val number: Double) : Expr()
data class Sum(val e1: Expr, val e2: Expr) : Expr()
object NotANumber : Expr()
}
}`