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() {
}
これはなぜですか?これは意図された動作ですか?ドキュメントはこれについて言及していないようです。
はい、それは意図された動作であることが判明しました。 によれば、ネストされていないサブクラスを許可する提案 :
提案:同じファイルでトップレベルのサブクラスを許可トップレベルの封印されたクラスの場合.
非最上位の封印されたクラスの場合、すべてのサブクラスはその内部で宣言する必要があります。したがって、そのようなクラスでは何も変更されません。
必要なシナリオが未解決の質問として表示されます。 https://youtrack.jetbrains.com/issue/KT-13495 にチケットがあります。現時点では誰も作業していないようです。提案の議論で、開発者は言います:
まあ、トップレベルのクラス用に解決されたいくつかの重要な実装の詳細(生成合成コンストラクターについて)がありますが、一般にそれをどのように行うかは明確ではありません。
ドキュメントから:
シールドクラスはそれ自体が抽象クラスであり、直接インスタンス化することはできず、抽象メンバーを持つことができます。
シールされたクラスは、非プライベートコンストラクターを持つことができません(これらのコンストラクターは、デフォルトではプライベートです)。
この例の使用方法は次のようになると思います:
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
}
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()
}
}`