Kotlin使用心得(十二):Sealed Class
如果要在Java中列舉,我們可能會用Enum,而在Kotlin中,除了Enum以外,還有一個更加強大的工具——Sealed Class。
Enum Class
在Kotlin中的枚舉類可以寫成:
然後使用when
來判斷:
枚舉類也可以自帶參數:
使用看看:
大guy~94醬。
Sealed Class:Enum Class 2.0
來看看Sealed Class有什麼特性吧!以下內文大部分從這篇文章翻譯過來:
首先,先創造一個名為Operation
的sealed class
,加上execute()
方法,來玩玩看:
sealed class
是個很酷的class,以上面的代碼為例:·類別中有4個class,分別是Add
、Subtract
、Multiply
與Divide
,而且
也只能有這4個class。什麼意思呢?
讓我們用execute()
方法來測試看看Operation
類別所有的枚舉情況:
fun execute(x: Int, op: Operation) = when (op) {
is Operation.Add -> x + op.value
is Operation.Subtract -> x - op.value
is Operation.Multiply -> x * op.value
is Operation.Divide -> x / op.value
}
如果我們試圖將其中一種枚舉情況刪除:
fun execute(x: Int, op: Operation) = when (op) {
is Operation.Add -> x + op.value
is Operation.Subtract -> x - op.value
is Operation.Multiply -> x * op.value
// delete this line
}
Compiler就會有森77的fu:
‘when’ expression must be exhaustive, add necessary ‘is Divide’ branch or ‘else’ branch instead
翻譯:when表達是應該是要全面性的,應該要包含「其他」情況
所以我們加入else
代表其他未過濾的枚舉情況,就可以解決這個警告:
fun execute(x: Int, op: Operation) = when (op) {
is Operation.Add -> x + op.value
is Operation.Subtract -> x - op.value
is Operation.Multiply -> x * op.value
else -> x
}
也就是說,你可以在Sealed Class中定義所有可能的情況,而在搭配when
的使用下,compiler會強迫我們得去注意到這些情況是否都有被處理到,是個非常貼心的設計。
想像一下今天我們要開個API給別人,他可能不會知道一個參數status
的所有種類,但透過Sealed Class與when
的組合,可以強迫這個API的使用者去了解所有的種類,並進行處理。
基本上一個Sealed Class的Subclass預設不帶任何參數,它會是個object:
注意到了嗎?當搭配when做使用的時候,但參數的Sealed Class subclass需要使用is
判斷,不帶參數的Object
不需要使用is
判斷:
fun execute(x: Int, op: Operation) = when (op) {
is Operation.Add -> x + op.value
is Operation.Subtract -> x - op.value
is Operation.Multiply -> x * op.value
is Operation.Divide -> x / op.value
Operation.Increment -> x + 1
Operation.Decrement -> x - 1
}
因為Kotlin中的Object
就是最簡單的單例模式,每個相同名稱的Object
其實都是一樣的,也只會有那麼一個。
Sealed class進階應用
我們可以將要對View
進行操作的功能封裝為一個sealed class(這邊為UiOp
),並在裡面列舉出我們將會進行的動作:
覆寫「+」號運算符,提升程式碼的易讀性:
看一下使用範例:
可以看到我們的方法run()
就是對View
進行操作。
進行什麼操作呢?這些操作已經用非常易讀的方式建構在ui
變數了,藉由適時的使用sealed class,可以方便地讓我們進行同一個系列的所有相關操作。