Reputation: 535
Image that I have two distinct Kotlin sealed classes.
sealed class Fruit {
object Apple : Fruit()
object Orange : Fruit()
object Banana : Fruit()
}
sealed class Vegetables {
object Broccoli : Vegetable()
object Carrot : Vegetable()
object Spinach : Vegetable()
}
Is it possible to define a type that is encompasses Fruits and Vegetables? Something like Produce = Fruit | Vegetable
So that you could write something like
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
}
.....
}
}
Upvotes: 0
Views: 726
Reputation: 198113
You can't create a union type, but you can always emulate it with another sealed type.
sealed class Produce {
class FruitProduce(val fruit: Fruit): Produce()
class VegetableProduce(val vegetable: Vegetable): Produce()
}
...and write
fun color(produce: Produce): String {
return when (produce) {
is Fruit -> when (produce.fruit) {
is Orange -> "Orange"
...
}
is Vegetable -> when (produce.vegetable) {
is Broccoli -> "Green"
...
}
}
}
Nothing better than this is possible today: you will need to wrap your fruit
and vegetable
objects in FruitProduce
and VegetableProduce
.
Upvotes: 2
Reputation: 18577
I think you're asking about a union type. There have been long discussions about adding one to Kotlin, but it doesn't look likely to happen soon.
Meanwhile, you can of course have an explicit parent class:
sealed class Produce
The rest then works pretty much as you'd expect:
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()
}
}
(You have to qualify Carrot
etc. unless you add static imports for them.)
(The nice thing about TODO()
is that it works both as documentation and as a way to get incomplete code to compile!)
Of course, this requires you to have access to both the types you want to combine, so you can add the common parent class. If you can't do that, a more long-winded option would be to use an Either
class (see e.g. here). That would need the produce to be explicitly wrapped and unwrapped, but is probably the nearest you can get in that case.
Upvotes: 4
Reputation: 28362
Just create a super class:
sealed class Produce
sealed class Fruit : Produce()
sealed class Vegetable : Produce()
Upvotes: 0