问题描述
我有两个不同的 Kotlin 密封类的图像。
sealed class Fruit {
object Apple : Fruit()
object Orange : Fruit()
object Banana : Fruit()
}
sealed class vegetables {
object broccoli : vegetable()
object Carrot : vegetable()
object Spinach : vegetable()
}
是否可以定义一个包含水果和蔬菜的类型?类似于 Produce = Fruit | vegetable
这样你就可以写出类似的东西
fun lookAtProduce(produce: Produce) {
when (produce) {
is Carrot -> {
return "Orange"
}
is Apple -> {
return "Red"
}
....
}
}
fun putItInSalad(vegetable: vegetable) {
when (vegetable) {
is Spinach -> {
return true
}
is Carrot -> {
return false
}
.....
}
}
解决方法
我认为您是在询问 union type。已经 long discussions 向 Kotlin 添加一个,但看起来不太可能很快发生。
同时,你当然可以有一个显式的父类:
sealed class Produce
剩下的就如你所愿:
sealed class Fruit : Produce() {
object Apple : Fruit()
object Orange : Fruit()
object Banana : Fruit()
}
sealed class Vegetable : Produce() {
object Broccoli : Vegetable()
object Carrot : Vegetable()
object Spinach : Vegetable()
}
fun lookAtProduce(produce: Produce) =
when (produce) {
is Vegetable.Carrot -> "Orange"
is Fruit.Apple -> "Red"
else -> TODO()
}
}
fun putItInSalad(vegetable: Vegetable) =
when (vegetable) {
is Vegetable.Spinach -> true
is Vegetable.Carrot -> false
else -> TODO()
}
}
(除非您为它们添加静态导入,否则您必须限定 Carrot
等。)
(TODO()
的好处在于它既可以作为文档,也可以作为编译不完整代码的方式!)
当然,这需要您对要组合的两种类型都具有访问权限,因此您可以添加公共父类。如果你不能这样做,一个更冗长的选择是使用 Either
类(参见例如 here)。这将需要明确包装和解开产品,但在这种情况下可能是您能得到的最接近的。
你不能创建联合类型,但你总是可以用另一个密封类型来模拟它。
sealed class Produce {
class FruitProduce(val fruit: Fruit): Produce()
class VegetableProduce(val vegetable: Vegetable): Produce()
}
...然后写
fun color(produce: Produce): String {
return when (produce) {
is Fruit -> when (produce.fruit) {
is Orange -> "Orange"
...
}
is Vegetable -> when (produce.vegetable) {
is Broccoli -> "Green"
...
}
}
}
今天没有比这更好的了:您需要将 fruit
和 vegetable
对象包装在 FruitProduce
和 VegetableProduce
中。
只需创建一个超类:
sealed class Produce
sealed class Fruit : Produce()
sealed class Vegetable : Produce()