深入理解Kotlin泛型

Kotlin 的泛型与 Java 一样,都是一种语法糖,即只在源代码中有泛型定义,到了class级别就被擦除了。 泛型(Generics)其实就是把类型参数化,真正的名字叫做类型参数,它的引入给强类型编程语言加入了更强的灵活性。

在这一节为大家继续带来Kotlin中的一些高级的内容:Kotlin中的泛型。

Why

  • 架构开发的一把利器;
  • 使我们的代码或开发出来的框架更加的通用;
  • 增加程序的健壮性,避开运行时可能引发的 ClassCastException;
  • 能够帮助你研究和理解别的框架;
  • 自己造轮子需要,能用泛型解决问题

在 Java 中,我们常见的泛型有:泛型类、泛型接口、泛型方法和泛型属性,Kotlin 泛型系统继承了 Java 泛型系统,同时添加了一些强化的地方。

目录

  • 泛型接口/类(泛型类型)
  • 泛型字段
  • 泛型方法
  • 泛型约束
  • 泛型中的out与in

泛型接口/类(泛型类型)

定义泛型类型,是在类型名之后、主构造函数之前用尖括号括起的大写字母类型参数指定:

泛型接口

//泛型接口
interface Drinks<T> {
    fun taste(): T
    fun price(t: T)
}

泛型类

abstract class Color<T>(var t: T/*泛型字段*/) {
    abstract fun printColor()
}

class Blue {
    val color = "blue"
}

class BlueColor(t: Blue) : Color<Blue>(t) {
    override fun printColor() {
        println("color:${t.color}")
    }

}

泛型字段

定义泛型类型字段,可以完整地写明类型参数,如果编译器可以自动推定类型参数,也可以省略类型参数:

abstract class Color<T>(var t: T/*泛型字段*/) {
    abstract fun printColor()
}

泛型方法

类型参数要放在方法名的前面:

fun <T> fromJson(json: String, tClass: Class<T>): T? {

    val t: T? = tClass.newInstance()
    return t
}

泛型约束

限定泛型参数的类型

// 泛型类型限定-1
// 所传递的类型T必须满足是User的子类 或User类
fun <T: User> fromJson(json: String, tClass: Class<T>): T? {
    ...
}
// 泛型类型限定-2
// 所传递的类型T必须同时满足 where 子句的所有条件,在下面的示例中,类型 T 必须既实现了 User, 也实现了 Comparable。
fun <T> fromJson(json: String, tClass: Class<T>): T? where T : User,T : Comparable<T> {
    ...
}

泛型中的out与in

在Kotlin中out代表协变,in代表逆变,为了加深理解我们可以将Kotlin的协变看成Java的上界通配符,将逆变看成Java的下界通配符:

out约束泛型参数的类型上限

泛型参数的类型 允许传入T,以及T 的子类

// 系统的类ArrayList声明了一个泛型T
class ArrayList<T>{

}
// Type mismatch.Required:  ArrayList<Int> , but Found:ArrayList<Number>
// 虽然Int是Number的子类,但kotlin认为ArrayList<Number>,不是 ArrayList<Int>的子类,所以会编译报错
val arrayList:ArrayList<Number> = ArrayList<Int>()//编译报错
// 在定义处使用out关键字声明,允许传入的泛型参数可以是T以及T的子类
class ArrayList<out T>{

}
// 也就是传入的泛型参数可以是 Number及Number的子类Int,Double,Float....
val arrayList:ArrayList<Number> = ArrayList<Int>()//编译正常

// 使用处使用out关键字声明
val arrayList:ArrayList<out Number> = ArrayList<Int>()//编译正常

in约束泛型参数的类型下限

泛型类型限定为T及T 的父类

// 在定义处使用out关键字声明,允许传入的泛型参数可以是T以及T的子类
class ArrayList<T>{

}

val arrayList:ArrayList<Int> = ArrayList<Number>()//编译报错
class ArrayList<in T>{

}
// 也就是传入的泛型参数可以是 Number及Number的子类Int,Double,Float....
// 使用处使用out关键字声明
val arrayList:ArrayList<Int> = ArrayList<Number>()//编译正常
val arrayList:ArrayList<in Int> = ArrayList<Number>()//编译正常,此时in可写可不写

总结

泛型种类 Java 中代码示例 Kotlin 中代码示例 说明
泛型类型 class Box<T> class Box<T> 泛型类型
泛型方法 <T> T fromJson(String json, Class<T> tClass) fun <T> fromJson(json: String, tClass: Class<T>): T? 泛型函数
有界类型参数 class Box<T extends Comparable<T> class Box<T : Comparable<T>> 泛型类型约束
上界通配符 void sumOfList(List<? extends Number> list) fun sumOfList(list: List<out Number>) 泛型上限约束
下界通配符 void addNumbers(List<? super Integer> list) fun addNumbers(list: List<in Int>) 泛型下限型约束
powered by GitbookCopyright © songyubao.com 2021 all right reserved。更新于: 14:10:41

results matching ""

    No results matching ""