Kotlin中另一个类中的密封类无法编译:无法访问“ <init>”,因为它是私有的

时间:2018-06-27 04:57:25

标签: class kotlin sealed

如果我使用的是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() {
}

为什么会这样?这是预期的行为吗?文档似乎没有提到这一点。

3 个答案:

答案 0 :(得分:5)

是的,事实证明这是预期的行为。根据{{​​3}}:

  

建议:在同一文件中允许顶级子类用于顶级密封类

     

对于非顶级密封类,应在其内部声明所有子类。因此,对于此类,什么也没有改变。

您想要的方案被列为一个悬而未决的问题。 the proposal allowing non-nested subclasses有一张票。目前似乎没有人对此进行研究。在讨论该提案时,开发人员说:

  

https://youtrack.jetbrains.com/issue/KT-13495

答案 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()
    }
}`