一、前言

<font face= 黑体>在 Kotlin 集合的变换与聚合 中我们已经将 Kotlin 的 集合变换与聚合 讲完了,我们都知道集合源码中用到了很多泛型的知识,所以我们今天我们来讲 Kotlin 的 泛型

二、泛型

2.1、泛型的基本概念

  • <font face= 黑体>泛型是一种类型层面的抽象;
  • <font face= 黑体>泛型通过泛型参数实现构造更加通用的类型的能力。

<font face= 黑体>比较两个整型的大小 Kotlin 代码可以这样写:

val max = maxOf(1, 2)

<font face= 黑体>maxOf() 的方法是这样的:

inline fun maxOf(a: Int, b: Int): Int

<font face= 黑体>但是呢,上面的 maxOf() 方法只能比较两个整型的大小,如果我们要比较任意类型(比如 Double 等)大小的方法要怎么办呢?所以泛型就是用来实现这种需求的,如下:

inline fun<T> maxOf(a: T, b: T): T

2.2、泛型的基本声明方法

  1. <font face= 黑体>函数声明泛型:

    fun<T> maxOf(a: T, b: T): T
  2. <font face= 黑体>类声明泛型:

    sealed calss List<T>

<font face= 黑体>这上面的 T 是形参,当我们要使用的使用的时候,需要传进去一个实参 ,如下:

val max: String = maxOf<String>("Hello", "World")

// 通过类型推到,上面的代码可以简写成这样
val max = maxOf("Hello", "World")

2.3、泛型的约束

<font face= 黑体>当一个泛型参数没有任何约束时,它可以进行的操作和运算是非常有限的,因为不能对实参做任何类型上的保证,这时候就需要用到泛型的约束。泛型的约束是指泛型的实参必须满足一定的规范,编译器在编译的过程中可以根据约束来检查所有泛型类型的实参并确保其满足约束条件。

<font face= 黑体>上面我们讲了一个比较任意类型大小的函数,如下:

fun<T> maxOf(a: T, b: T): T {
    // 编译报错
    return if(a > b) a else b
}

<font face= 黑体>显然,上面的代码会报错,a 和 b 都是泛型,不可以用 > 号,这时候,我们可以给泛型 T 加一个 Comparable 约束,就可以实现 a > b,这时候 T 需要实现 Comparable 接口,代码如下所示:

fun<T : Comparable<T>> maxOf(a: T, b: T): T {
    return if(a > b) a else b
}

// String 已经实现类 Comparable 接口,所以可以直接用
val max = maxOf("Hello", "World")

2.4、泛型的多个约束

<font face= 黑体>在我们实际开发中,有时会遇到一个泛型有多个约束条件的情况,比如两个数据既要比较大小,还要执行大的数据类型的 invoke 方法,这时我们就可以使用 Kotlin 为我们提供的 where 关键字来进行多个条件的约束,具体代码如下:

fun <T> callMax(a: T, b: T)
where T : Comparable<T>, T : () -> Unit {
    if (a > b) a() else b()
}

2.5、多个泛型参数

<font face= 黑体>我们有这样一个需求:比较两个 T 类型的数据大小,并调用大 T 的 invoke 方法,并返回一个 R 类型的数据,这时就要使用多个泛型参数了,代码如下:

fun <T, R> callMax(a: T, b: T): R
where T : Comparable<T>, T : () -> R, R : Number {
    return if (a > b) a() else b()
}

<font face= 黑体>多个泛型参数的例子我们平时用的最多的就是 Map<K, V>。

2.6、Java 的泛型约束

<font face= 黑体>泛型约束的概念 Java 也有,写法是 T extends ... 我们来看一下:

public static <T extends Comparable<T>> T maxOf(T a, T b) {
    if (a.compareTo(b) > 0) 
        return a;
    else 
        return b;
}

三 、源码

源码 已上传至 github,有需要可以直接下载。


Maenj_Ba_lah
28 声望5 粉丝

真正的大师,永远怀着一颗学徒的心。