【问题标题】:Combine multiple is in when clause in Kotlin在 Kotlin 的 when 子句中组合多个 is
【发布时间】:2018-11-16 12:57:34
【问题描述】:

假设我有以下:

fun makeSound(val animal: Animal) = when(animal) {
  is Lion -> animal.roar()
  is TRex -> animal.roar()
  is Cow -> animal.moo()
}

通常我会通过简单地添加RoaringAnimal 接口并询问is RoaringAnimal 来简化此操作。但是还有另一种方法可以将多个is 子句组合成一个子句吗?

【问题讨论】:

  • 你为什么想要在这里结合is Lionis TRex的东西?以您展示的方式使用它还不够简单吗?否则,如果可能的话,我宁愿更新你的层次结构......(旁注:val 在这里可能是错误的,= 需要详尽的when

标签: generics kotlin


【解决方案1】:

通常,您可以按照 Yoni 的回答中所示组合子句。

但在roar 定义在LionTRex 上而不是Animal 上的特定情况下,您不能。

这是因为编译器插入了一个智能转换:

is Lion -> animal.roar()

真的

is Lion -> (animal as Lion).roar()

但在is Lion, is TRex -> 子句中,它不知道要插入什么演员表。

原则上,可以通过插入另一个when 来扩展编译器以处理此类情况:

is Lion, is TRex -> animal.roar()

会变成

is Lion, is TRex -> when(animal) {
    is Lion -> animal.roar() // works as before
    is TRex -> animal.roar()
}

但我不希望会发生这种情况

【讨论】:

  • “原则上,编译器可以扩展来处理这种情况......”是的,实际上这正是我认为的行为。感谢您解释编译器不知道要插入哪个智能转换。
【解决方案2】:

更新:下面的答案是在问题指定roaranimal 参数上的方法之前编写的。就目前的问题而言,下面的答案将不再有效,但它仍然显示了如何在 when 语句中将多个条件组合在一行中。

您可以将它们组合起来:

fun makeSound(animal: Animal) = when(animal) {
  is Lion, is TRex -> roar()
  is Cow -> moo()
}

【讨论】:

  • 这将如何工作?这不仅会捕获通用的Animal 类型吗?
  • roar 只有在你传入LionTRex 时才会被调用。你所说的“抓住”到底是什么意思?我想知道您是否需要稍微澄清一下您的问题?
  • 啊,是的。我的问题并不准确。我现在修改了。
  • 正如 Alexey 所说,现在您已更新您的问题以指定 roarLionTRex 上的一种方法,那么不,没有(好的)方法这没有新的接口或基类。 (您可以使用反射,但这不是一个好主意。)
【解决方案3】:
fun makeSound(val animal: Animal) = when(animal) {
  Lion, TRex -> animal.roar()
  Cow -> animal.moo()
}

你不需要“是”。只需在此处使用逗号分隔符即可。

【讨论】:

    【解决方案4】:

    在我看来,您在这里所做的事情就像 code smell。为什么不使用多态来解决这类问题?

    interface Animal {
        fun makeSound()
    }
    class Lion : Animal {
        override fun makeSound() { println("roar") }
    }
    class Trex : Animal {
        override fun makeSound() { println("ROAAAARRRR") }
    }
    class Cow : Animal {
        override fun makeSound() { println("moo") }
    }
    
    fun makeSound(animal: Animal) {
        animal.makeSound()
        // due tue "late binding", this will automatically call the correct method - no need to check what kind of animal it is! 
    }
    

    【讨论】:

    • 就像我在问题中所说的,使用接口是绝对可能的。但是,问题不是最佳实践之一,而是 Kotlin 中的可能性。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-07
    • 1970-01-01
    • 2016-05-10
    • 2011-04-12
    • 1970-01-01
    相关资源
    最近更新 更多