JGSK - 27.泛型 - Kotlin篇

Table Of Contents

泛型

基本概念

基本概念同 Java。

创建泛型

同 Java。

class Capture<T>(val t: T)

使用泛型

val integerCapture = Capture(10)
val nint10 = integerCapture.t
val stringCapture = Capture("Hi")
val str = stringCapture.t

协变与逆变

在 Kotlin 中,这两种特性都是默认不支持的。

注意,函数的参数是逆变的,函数的返回值是协变的。

使用协变

使用协变需要在类型前加上 out,相比较 Scala 使用的 + 可能更能让人理解。

定义一个支持协变的类,协变类型参数只能用作输出,所以可以作为返回值类型但是无法作为入参的类型

class CovariantHolder<out A>(val a: A) {
    fun foo(): A {
        return a
    }
}

使用该类

var strCo: CovariantHolder<String> = CovariantHolder("a")
var anyCo: CovariantHolder<Any> = CovariantHolder<Any>("b")
anyCo = strCo

使用逆变

使用逆变需要在类型前加上 in

定义一个支持逆变的类,逆变类型参数只能用作输入,所以可以作为入参的类型但是无法作为返回值的类型

class ContravarintHolder<in A>(a: A) {
    fun foo(a: A) {
    }
}

使用该类

var strDCo = ContravarintHolder("a")
var anyDCo = ContravarintHolder<Any>("b")
strDCo = anyDCo

类型通配符

Kotlin 使用 * 作为通配符,而 Java 是 ,Scala 是 _

fun foo2(capture: Capture<*>) {
}

类型参数边界

Kotlin 并没有上下边界这种说法。但是可以通过在方法上使用协变和逆变来达到同样的效果。

使用协变参数达到上边界的作用,这里的 out 很形象地表示了协变参数只能用于输出

fun foo3(list: MutableList<out Num>) {
    val num: Num = list.get(0)
    println(num)
}

使用逆变参数达到下边界的作用,这里的 in 很形象地表示了逆变参数只能用于输入

fun foo4(list: MutableList<in Num>) {
    list.add(Num(4))
    val num: Any? = list.get(0)
    println(num)
}

项目源码见 JGSK/_27_generics