Статус | Ожидание | Реальность |
---|---|---|
🚫 | Корректно конвертируется в структуру, которую можно передать в switch-конструкцию и сделать exhaustive | Генерируется класс с наследниками. Передав в switch нет подсказок об exhaustive |
В Kotlin-е sealed-классы могут использоваться в when
-выражениях, которые могут подсказывать программисту
о забытых ветках:
sealed class MySealed {
object Object : MySealed()
class Simple(val param1: String) : MySealed()
data class Data(val param1: String, val param2: Boolean) : MySealed()
}
private fun example(s: MySealed) {
when (s) {
MySealed.Object -> TODO()
is MySealed.Simple -> TODO()
is MySealed.Data -> TODO()
}
}
Но в Swift такой класс сконвертируется как обычный класс с наследниками, который бесполезен при подстановке в switch
:
func example(s: MySealed) {
switch s {
default:
print("Sad")
}
}
В Swift-е роль sealed-классов выполняют enum-ы, и можно было бы написать специальный bridge-код для конвертации sealed-классов в Swift-овый enum.
enum MySealedSwift {
case object
case simple(String)
case data(String, Bool)
public init(_ obj: MySealed) {
if obj is MySealed.Object {
self = .object
} else if let obj = obj as? MySealed.Simple {
self = .simple(obj.param1)
} else if let obj = obj as? MySealed.Data {
self = .data(obj.param1, obj.param2)
} else {
fatalError("MySealedSwift not syncronized with MySealed class")
}
}
}
// Использование
func switchUsage(mySealed: MySealed) {
switch MySealedSwift(mySealed)
case .obj:
// do stuff
case let .simple(param1):
// do stuff
case let .data(param1, param2):
// do stuff
}
Плагин moko-kwift умеет генерировать такой маппинг с помощью фичи.
kswift {
install(dev.icerock.moko.kswift.plugin.feature.SealedToSwiftEnumFeature)
}
Но есть некоторые особенности, см. moko-kswift overview