返回

Kotlin 中的协变和逆变泛型:类型安全性与通用性

Android

在 Kotlin 中,泛型是一项强大的特性,它允许您创建可与不同类型一起使用的类和方法。泛型通常通过使用尖括号和类型参数来定义,例如:

class GenericClass<T> {
    fun genericMethod(t: T) {
        // do something with t
    }
}

该类可以与任何类型一起使用,例如:

val stringList: GenericClass<String> = GenericClass<String>()
stringList.genericMethod("Hello, world!")

val integerList: GenericClass<Int> = GenericClass<Int>()
integerList.genericMethod(42)

协变泛型

协变泛型允许您将子类型的实例传递给需要父类型实例的方法或类。例如,以下代码是允许的:

class Parent {
    fun parentMethod() {
        // do something
    }
}

class Child : Parent() {
    fun childMethod() {
        // do something else
    }
}

fun main() {
    val parentList: List<Parent> = listOf(Parent(), Child())
    for (parent in parentList) {
        parent.parentMethod() // OK
        // parent.childMethod() // Error: Child method not available in Parent reference
    }
}

在上面的示例中,parentList是一个包含 ParentChild 实例的列表。我们可以在 parentList 上调用 parentMethod() 方法,因为 ChildParent 的子类。但是,我们不能调用 childMethod() 方法,因为 Parent 的引用没有 childMethod() 方法。

逆变泛型

逆变泛型允许您从返回父类型实例的方法或类中接收子类型的实例。例如,以下代码是允许的:

class Parent {
    fun parentMethod(): Parent {
        // do something
        return this
    }
}

class Child : Parent() {
    override fun parentMethod(): Child {
        // do something else
        return this
    }

    fun childMethod() {
        // do something else
    }
}

fun main() {
    val child: Child = Child()
    val parent: Parent = child.parentMethod() // OK
    parent.parentMethod() // OK
    // parent.childMethod() // Error: Child method not available in Parent reference
}

在上面的示例中,child.parentMethod() 返回一个 Child 实例,但我们将其赋给了一个 Parent 变量。这是允许的,因为 ChildParent 的子类。我们可以在 parent 上调用 parentMethod() 方法,因为它是 Parent 的方法。但是,我们不能调用 childMethod() 方法,因为 Parent 的引用没有 childMethod() 方法。

协变和逆变泛型的安全性和限制

协变和逆变泛型是非常强大的特性,但它们也有一些安全性和限制。

  • 协变泛型仅适用于方法或类的输入类型。您不能将协变泛型用于输出类型。
  • 逆变泛型仅适用于方法或类的输出类型。您不能将逆变泛型用于输入类型。
  • 协变和逆变泛型只能用于类和接口类型。它们不能用于基本类型或数组类型。
  • 协变和逆变泛型只能用于单一类型参数。它们不能用于多个类型参数。

结论

协变和逆变泛型是 Kotlin 中非常强大的特性,它们允许您创建更灵活、更类型安全的泛型类和方法。但是,在使用协变和逆变泛型时,您需要了解它们的安全性限制。