-
SealedClass
又稱為印章類或密封類剃浇,密封類用于子類類型有限的類巾兆。 - 密封類與枚舉的區(qū)別在于,密封類更加在意類型虎囚,枚舉更加在意數(shù)據(jù)角塑。
密封類用來表示受限的類繼承結(jié)構(gòu),當(dāng)一個(gè)值為有限的幾種類型而不能有任何其他類型淘讥。在某種意義上圃伶,密封類是枚舉類的擴(kuò)展。枚舉類型的值集合是受限的蒲列,但每個(gè)枚舉常量只存在一個(gè) 實(shí)例窒朋,密封類的一個(gè)子類可以有包含狀態(tài)的多個(gè)實(shí)例。
Kotlin中密封類的出現(xiàn)蝗岖,在于它定義了一種受限的類繼承結(jié)構(gòu)侥猩,可以保證編寫出更加安全的代碼。
由來
//定義接口
interface InterfaceName
//兩個(gè)類實(shí)現(xiàn)接口
class ClassName1:InterfaceName{}
class ClassName2:InterfaceName{}
//通過傳入接口對象使用when來判斷傳入的對象是那種類型抵赢。
fun check(i:InterfaceName):String = when(i){
is ClassName1->"1"
is ClassName2->"2"
else -> throw IllegalArgumentException("Unknown class")
}
//測試運(yùn)行
fun main(args:Array<String>){
val obj = ClassName1()
val result = check(obj)
println(result)//1
}
上面代碼存在潛在的問題:加入此時(shí)再添加一個(gè)子類欺劳,此時(shí)when
并沒有發(fā)現(xiàn)子類增加了也不會報(bào)錯(cuò),可能需要給when
增加一個(gè)新分支铅鲤,但由于沒有報(bào)錯(cuò)可能就會被我們忽略了划提。基于以上原因彩匕,Kotlin為了解決上述潛在問題便提出了密封類腔剂。
聲明
聲明密封類使用關(guān)鍵字sealed
修飾符媒区,需要再類名前添加sealed
修飾符驼仪。密封類可以有子類掸犬,但所有子類必須要內(nèi)嵌到密封類中。
sealed class Compute{
class Add(val value:Int):Compute()
class Substract(val value:Int):Compute()
class Multiply(val value:Int):Compute()
class Divide(val value:Int):Compute()
}
sealed class Cmd{
class Play(val url:String, val pos:Long=0):Cmd()
class Seek(val pos:Long):Cmd()
object Pause:Cmd()
object Resume:Cmd()
object Stop:Cmd()
}
使用注意
-
sealed
關(guān)鍵字不能修飾接口interface
和抽象類abstract class
- 密封類時(shí)自身抽象的绪爸,不能直接實(shí)例化但可以有抽象成員湾碎。
- 密封類不允許擁有非私有
private
構(gòu)造函數(shù),因?yàn)樗臉?gòu)造函數(shù)默認(rèn)是私有的奠货。 - 密封類封裝子類的類(間接繼承者 )可以放到任何位置介褥,而無需在同樣一個(gè)文件中。
密封類的關(guān)鍵好處在于使用when
表達(dá)式時(shí)递惋,如果能驗(yàn)證語句覆蓋了所有情況則無需為該語句再添加一個(gè)else
子句柔滔。
Kotlin中類不是默認(rèn)final
的嗎?那么密封類為什么可以繼承呢萍虽?因?yàn)楸?code>sealed修飾的類默認(rèn)是open
的睛廊,所以可以被繼承,另外無需顯式地使用open
修飾符杉编。