Android Kotlin 泛型(四)

首先申明下,本文为笔者学习《Kotlin 程序开发入门精要》的笔记,并加入笔者自己的理解和归纳总结。

1. 泛型

所谓泛型,就是指在定义数据结构时,只指定类型的占位符,待到使用该数据结构时再指定具体的数据类型。

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

class Data<T>(v: T) {
    var value = v
}

fun main(args: Array<String>) {
    // 创建类的实例时指定类型参数
    var strData: Data<String> = Data("Hello World")
    // 编译器会进行类型推断
    var intData = Data(12)

    println(strData.value)  // Hello World
    println(intData.value)  // 12
}

2. 泛型函数

泛型函数的类型参数要放在函数名的前面。

fun <T> copy(d: Data<T>): Data<T> {
    return Data(d.value)
}

3. 泛型约束

泛型约束常见的是上界约束,类似于Java的extends关键字,在冒号(:)后面指定的类型就是泛型参数的上界。如果没有指定,则默认使用的上界类型是Any?

fun <T : Comparable<T>> equals(v1: T, v2: T): Boolean {
    return v1.compareTo(v2) == 0
}

fun main(args: Array<String>) {
    println(equals(1, 1))  // true
    println(equals(1, 2))  // false
}

在定义泛型的尖括号<>内,只允许定义唯一一个上界,如果需要指定多个上界,使用单独的where子句。

interface ICopy<T> {
    fun copy(): T
}

fun <T> copy(t: T) : T
      where T : Comparable<T>, T : ICopy<T> {
    return t.copy()
}

4 . 类型变异

kotlin泛型没有提供通配符,取而代之的是outin关键字。

out声明的泛型占位符只能在获取泛型类型值的地方,如函数的返回值。

class OutData<out T>(val v: T) {

    fun getValue(): T {
        return v
    }
}

fun main(args: Array<String>) {
    var strData = OutData<String>("Hello World")
    var objData: OutData<Any> = OutData("Object")

    objData = strData  // OutData<String>可以看做OutData<Any>的子类
}

in声明的泛型占位符只能在设置泛型值的地方,如函数的参数。

class InData<in T>() {

    fun setValue(t: T) {
    }
}

fun main(args: Array<String>) {
    var intData = InData<Int>()
    var anyData = InData<Any>()

    intData = anyData  // InData<Any>可以看做InData<Int>的子类
}

5. 类型投射

A是类B的父类,但Array<A>Array<B>不是继承关系,outin关键字可以对类型投射。

open class A{}
class B : A() {}

fun copy(from: Array<out A>, to: Array<A>) {
}

fun fill(dest: Array<in B>, v: B) {	
}

fun main(args: Array<String>) {
    var aArr: Array<A> = arrayOf(A(), A())
    var bArr: Array<B> = arrayOf(B(), B())

    copy(bArr, aArr)
    fill(aArr, B())
}
  • Kotlin 中的out A类似于 Java 中的? extends A,即泛型参数类型必须是A或者A的子类,用来确定类型的上限
  • Kotlin 中的in B类似于 Java 中的? super B,即泛型参数类型必须是B或者B的父类,用来确定类型的下限

当我们不知道泛型参数的类型信息时,但仍需要安全的使用它时,可以使用星投影,用星号*表示。如果类型定义为interface Function<in T, out U>,那么可以出现以下几种信号投射。

Function<*, String>,代表Function<in Nothing, String>
Function<Int, *>,代表Function<Int, Out Any?>
Function<*, *>,代表Function<in Nothing, Out Any?>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值