【问题标题】:Sealed class in Kotlin, Incompatible types errorKotlin 中的密封类,不兼容类型错误
【发布时间】:2018-06-15 19:41:12
【问题描述】:

我有以下 Kotlin 代码。一个名为Animal 的密封类,以及两个对象类DogCat 继承自密封类Animal。我在 is Cat 案例的 when 子句中收到此错误。

Incompatible types: Cat and Dog

为什么会出现这个错误?如何在 Kotlin 中使用密封类进行这种类型的操作?密封类是做多态的好选择吗?

sealed class Animal {
  abstract fun speak()
}

object Dog : Animal() {
    override fun speak() { println("woof") }
}

object Cat : Animal() {
    override fun speak() { println("meow") }
}

fun main(args: Array<String>) {
    var i = Dog
    i.speak()
    when(i) {
        is Dog -> {
            print("Dog: ")
            i.speak()
        }
        is Cat -> {
            print("Cat: ")
            i.speak()
        }
    }
}

【问题讨论】:

    标签: kotlin sealed-class


    【解决方案1】:

    缺少的部分是var i: Animal = Dog

    基本上编译器在抱怨类型 - Cat 不是 Dog 的子类型(但它们都是 Animal 的子类型,这就是为什么如果您明确设置基本类型代码将编译和工作

    【讨论】:

    • 在这种情况下使用密封类与抽象类有什么好处吗?密封类适合做这样的多态吗?
    • @s-hunter,当您有一组封闭的类型并想要开放功能时,密封类是合适的。您添加的功能通常会针对集合中的每种类型以不同的方式实现,而无需这些类型符合某些通用接口。
    • @s-hunter 好吧,密封类与多态并没有真正的关系,它们只是提供语义来描述有限层次结构并使用它,例如,在when 构造中
    • @ruX,它仍然是多态性。如果您有动物和适用于任何动物的函数,则调用该函数,其行为取决于您拥有的动物的实际类型。您可以在不更改函数调用的情况下更改实际类型并获得不同的行为。这与基于继承的多态性之间的主要区别在于,编写新函数不需要修改任何内容,但添加新类型则需要。
    【解决方案2】:

    您的代码有两个地方编译器作为一个整体并不真正理解:

    1. when 子句中,检查Dog 类型的变量是否真的是is Dog
    2. when 子句中,检查Dog 类型的变量是否为Cat

    这与编译器有点矛盾,因为这两种类型只共享一个超类型。问题实际上是您的变量没有明确声明其类型。由于将Dog 实例分配给您的var i,编译器推断其类型,当然是Dog。之后的一切都有意义:无需检查实例类型,它肯定是Dog

    要使代码工作,您必须声明var i: Animal,显式键入。另外,always consider using val in favor of var

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-23
      • 2011-07-18
      • 1970-01-01
      相关资源
      最近更新 更多