Запечатанные классы внутри другого класса в Kotlin не могут быть скомпилированы: не могут получить доступ к '<init>', это личное - PullRequest
0 голосов
/ 27 июня 2018

Если я использовал пример из документов ,

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 голосов
/ 14 июля 2018

В Kotlin 1.0 закрытая функциональность довольно ограничена. За Например, все подклассы должны быть вложенными, и подкласс не может быть сделан класс данных (классы данных рассматриваются далее в этой главе). Котлин 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()
    }
}`
0 голосов
/ 14 июля 2018

Да, это оказывается намеченным поведением. Согласно предложение разрешает не вложенные подклассы :

Предложение: разрешить подклассы верхнего уровня для запечатанного класса верхнего уровня в том же файле.

Для запечатанного класса не верхнего уровня все подклассы должны быть объявлены внутри него. Так что для таких классов ничего не меняется.

Сценарий, который вы хотите, указан как открытый вопрос. Билет на это https://youtrack.jetbrains.com/issue/KT-13495. В данный момент никто не работает над этим. При обсуждении предложения разработчик говорит:

Ну, есть некоторые нетривиальные детали реализации (о синтетических конструкторах генерации), которые были решены для классов верхнего уровня, но как это вообще сделать, неясно.

0 голосов
/ 27 июня 2018

Из документации:

Запечатанный класс сам по себе абстрактный, его нельзя создать напрямую и может иметь абстрактные члены.

Запечатанным классам не разрешается иметь не частные конструкторы (их конструкторы по умолчанию закрыты).

Я думаю, вы должны использовать пример:

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
}
...