0

我有两个不同的 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
    }
    .....
  }
}
4

3 回答 3

2

我想你问的是union type关于在 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)。这将需要明确包装和打开产品,但在这种情况下可能是您可以获得的最接近的产品。

于 2021-06-10T21:29:48.863 回答
1

您无法创建联合类型,但您始终可以使用另一种密封类型来模拟它。

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"
      ...
    }
  }
}

今天没有比这更好的了:你需要将你的fruitandvegetable对象包裹在FruitProduceand中VegetableProduce

于 2021-06-10T22:11:10.757 回答
0

只需创建一个超类:

sealed class Produce
sealed class Fruit : Produce()
sealed class Vegetable : Produce()
于 2021-06-10T21:28:33.890 回答