在本文中,您將在示例的幫助下了解Sealed (密封)類,如何創(chuàng)建它們以及何時(shí)使用它們。
當(dāng)值只能從有限的集合(受限的層次結(jié)構(gòu))中包含一個(gè)類型時(shí),將使用密封類。
在詳細(xì)介紹密封類之前,讓我們探討它們解決的問(wèn)題。讓我們舉個(gè)實(shí)例:
class Expr class Const(val value: Int) : Expr class Sum(val left: Expr, val right: Expr) : Expr fun eval(e: Expr): Int = when (e) { is Const -> e.value is Sum -> eval(e.right) + eval(e.left) else -> throw IllegalArgumentException("Unknown expression") }
在上面的程序中,基類 Expr 有兩個(gè)派生類 Const (表示一個(gè)數(shù)字)和 Sum (表示兩個(gè)表達(dá)式的和)。在這里,必須使用 else 分支來(lái)處理 when表達(dá)式中的默認(rèn)條件。
現(xiàn)在,如果您從Expr類派生一個(gè)新的子類,則編譯器將不會(huì)檢測(cè)到任何東西,因?yàn)?else 分支會(huì)對(duì)其進(jìn)行處理,這可能會(huì)導(dǎo)致錯(cuò)誤。 如果在添加新的子類時(shí)編譯器發(fā)出錯(cuò)誤,那就更好了。
要解決此問(wèn)題,可以使用密封類。 如前所述,密封類限制了創(chuàng)建子類的可能性。 而且,當(dāng)您在when表達(dá)式中處理密封類的所有子類時(shí),不必使用else分支。
要?jiǎng)?chuàng)建密封類,請(qǐng)使用密封修飾符 sealed 。例如,
sealed class Expr
這是使用密封類解決上述問(wèn)題的方法:
sealed class Expr class Const(val value: Int) : Expr() class Sum(val left: Expr, val right: Expr) : Expr() object NotANumber : Expr() fun eval(e: Expr): Int = when (e) { is Const -> e.value is Sum -> eval(e.right) + eval(e.left) NotANumber -> java.lang.Double.NaN }
正如你所看到的,沒(méi)有 else 分支。如果您從 Expr 類派生了一個(gè)新的子類,除非子類是在 when 表達(dá)式中處理的,否則編譯器將報(bào)告。
密封類的所有子類必須在聲明密封類的同一文件中聲明。
密封類本身是抽象的,您不能從中實(shí)例化對(duì)象。
不能創(chuàng)建密封類的非私有構(gòu)造函數(shù);默認(rèn)情況下,它們的構(gòu)造函數(shù)是 private。
枚舉類和密封類非常相似。枚舉類型的值集也像密封類一樣受到限制。
唯一的區(qū)別是,枚舉只能有一個(gè)實(shí)例,而密封類的子類可以有多個(gè)實(shí)例。