シールクラスは限定的なクラス階層を表すために使用されます。
このクラスでは値は限定されたセットの型の1つを持つことができますが、それ以外の型を持つことが出来ません。
ある意味で、これらは列挙型クラスの拡張です。:
列挙型の値のセットも制限されますが、各列挙型定数は単一のインスタンスとしてのみ存在するのに対し、シールクラスのサブクラスは、状態を含むことができる複数のインスタンスを持てます。
シールクラスを宣言するには、クラス名の前にsealed修飾子を加えます。シールクラスはサブクラスを持つことができますが、それらはすべてシールクラス自体と同じファイルで宣言する必要があります。 (Kotlin 1.1より前は、ルールはさらに厳格でした。クラスは、シールクラスの宣言内にネストする必要がありました)。
sealed class Expr data class Const(val number: Double) : Expr() data class Sum(val e1: Expr, val e2: Expr) : Expr() object NotANumber : Expr()
(上記の例では、Kotlin 1.1で追加された新機能を利用しています。
データクラスがシールクラスを含む他のクラスを継承出来るようになりました。)
シールクラス自体は抽象クラスであり、直接インスタンス化は出来ず、抽象メンバを持てません。
シールクラスは、privateではないコンストラクタを持つことはできません。(それらのコンストラクタはデフォルトでprivateです)。
シールクラスのサブクラスを継承するクラス(間接継承)は、必ずしも同じファイル内ではなく、どこにでも配置できることに注意してください。
シールクラスを使用する主な利点は、when式で使用するときに役立ちます。ステートメントがすべてのケースをカバーしていることを確認できる場合は、ステートメントにelse句を追加する必要はありません。ただし、これはwhenをステートメントとしてではなく、式として使用(し、その結果を使用)する場合にのみ機能します。
fun eval(expr: Expr): Double = when(expr) { is Const -> expr.number is Sum -> eval(expr.e1) + eval(expr.e2) NotANumber -> Double.NaN // 全てのケースをカバーしている為、`else`句は必要ありません。 }