Sealed classes inside another class in Kotlin can't be compiled: cannot access '<init>' it is private

*爱你&永不变心* 提交于 2020-04-12 08:14:12

问题


If I used the example from the 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()
}

it does not compile, with the error:

Cannot access '<init>', it is private in 'Expr'.

However, moving it outside the enclosing class makes it compile:

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() {
}

Why is this so? Is this an intended behavior? The docs does not seem to mention this.


回答1:


Yes, it turns out to be intended behavior. According to the proposal allowing non-nested subclasses:

Proposal: allow top-level subclasses for a top-level sealed class in the same file.

For a non top-level sealed class all subclasses should be declared inside it. So, for such classes nothing changes.

The scenario you want is listed as an open question. There is a ticket for it at https://youtrack.jetbrains.com/issue/KT-13495. Nobody seems to be working on it at the moment. In the discussion of the proposal, the developer says:

Well, there is some not-trivial implementations details(about generation synthetic constructors) which was solved for top-level classes but how do it in general is not clear.




回答2:


From the documentation:

A sealed class is abstract by itself, it cannot be instantiated directly and can have abstract members.

Sealed classes are not allowed to have non-private constructors (their constructors are private by default).

I guess the way you should use the example is like:

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
}



回答3:


In Kotlin 1.0, the sealed functionality is rather restricted. For instance, all the subclasses must be nested, and a subclass can’t be made a data class ( data classes are covered later in this chapter). Kotlin 1.1 relaxes the restrictions and lets you define subclasses of sealed classes anywhere in the same file. In the given example, it is not allowed up until now. May be, in later release versions, they will relax this restriction. However, you can do this:

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


来源:https://stackoverflow.com/questions/51054789/sealed-classes-inside-another-class-in-kotlin-cant-be-compiled-cannot-access

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!