【问题标题】:how do expose inferred types for extends class in kotlin?如何在 kotlin 中公开扩展类的推断类型?
【发布时间】:2026-01-09 04:00:02
【问题描述】:

我正在学习 kotlin 中的类扩展,我遇到了这个错误。 你能解释一下为什么会这样吗:

open class Animal
class Zebra: Animal()

fun main() {
    var animal = Zebra()
    animal = Animal()  // Error: Type mismatch
}

【问题讨论】:

  • animalZebra 类型,而Animal 不是Zebra(即不是Zebra 的子类),这就是您不能将Animal 分配给animal 的原因。

标签: kotlin extends


【解决方案1】:

var animal = Zebra() 只是一个语法糖

var animal:Zebra = Zebra()

这应该很清楚。

那么为什么我们不能分配超类呢? 因为在对象而不是引用上调用方法。如果将来Zebra 类将具有方法fun roar(),则编译器将无法确保animal 变量能够执行,如果它允许在那里分配其他声明类型或子类这种类型

阅读更多:

【讨论】:

    【解决方案2】:

    Kotlin 的类型推断是 Kotlin 中最受欢迎的功能之一 JVM 世界。如此流行以至于 Java 10 引入了类型推断作为 好(与 Kotlin 相比有限)。不过也有一些危险 在使用此功能时。最重要的是,我们需要记住, 赋值的推断类型是右侧的确切类型, 而不是超类或接口:

    在大多数情况下,这不是问题。当我们限制太多时 类型推断,我们只需要指定它,我们的问题就解决了:

    open class Animal
    class Zebra: Animal()
    fun main() {
        var animal: Animal = Zebra()
        animal = Animal()
    }
    

    但是,当我们不控制图书馆时,就没有这样的舒适感 或其他模块。在这种情况下,推断类型说明可以是 真的很危险。让我们看一个例子。 假设您有以下接口用于表示 汽车厂

    interface CarFactory {
      fun produce(): Car
    }
    

    如果没有指定其他内容,也会使用默认汽车:

    val DEFAULT_CAR: Car = Fiat126P()
    

    现在,你们所有的工厂都只能生产 Fiat126P 。不好。如果 你自己定义了这个接口,这个问题很可能是 很快就被抓住了,很容易修复。虽然,如果它是外部的一部分 API(可能从某些地方使用的元素(类、函数、对象) 外部模块或我们由不同开发人员维护的部分代码。 例如,在图书馆中,这些都是公共和受保护的类,功能 和对象声明),您可能会首先被愤怒的用户告知。 除此之外,返回类型是重要信息,当一些 - 不太了解API,所以为了可读性,我们 应该使其明确,尤其是在我们的 API 中可见的部分 外部(如此暴露的 API)。

    【讨论】:

    • 严格类型推断更安全,而不是更危险。编译错误是安全的。留下潜在的运行时错误是危险的。
    【解决方案3】:

    Kotlin(实际上是 IDE)向 Zebra 推断动物的类型:

    var animal = Zebra()   // animal is of type Zebra
    animal = Animal()      // type mismatch since Animal is not a Zebra
    

    如果您明确指定类型为 Animal,那么您可以在下一行分配一个 Animal:

    var animal: Animal = Zebra()   // animal is of type Animal
    animal = Animal()              // this works
    

    【讨论】: