Skip to content

Latest commit

 

History

History
66 lines (47 loc) · 2.61 KB

泛型.md

File metadata and controls

66 lines (47 loc) · 2.61 KB

Kotlin泛型

  • 泛型
  • 泛型约束:我们可以使用泛型约束来设定一个给定参数允许使用的类型,Kotlin 中使用 : 对泛型的的类型上限进行约束。最常见的约束是上界(upper bound), 默认的 上界是 Any?

//T就是上界 Comparable 的子类型可以替代 T
  fun <T : Comparable<T>> sort(list: List<T>) {
    // ……
  }

  • 型变:Kotlin 中没有通配符类型,它有两个其他的东西:声明处型变与类型投影。
  • 声明处的类型变异使用协变注解修饰符:in、out,消费者 in, 生产者 out。 使用 out 使得一个类型参数协变,协变类型参数只能用作输出,可以作为返回值类型但是无法作为入参的类型
  • in 使得一个类型参数逆变,逆变类型参数只能用作输入,可以作为入参的类型但是无法作为返回值的类型
  • 类型投影:使用处型变 和 星投影,使用处型变就是在函数参数处使用型变来控制错误的发生。

java泛型中的一些概念

  • java 中的通配符类型参数: ? extends E
  • 通配符<? extends E>表示包括E在内的所有子类,称为协变
  • 通配符<? super E>表示包括E在内的所有父类,称为逆变
  • 协变: 表示包括E在内的所有子类,泛型对象只能读取,称为生产者
  • 逆变: 表示包括E在内的所有父类,泛型对象只能写入,称为消费者

星投影

  • Kotlin的泛型使用基本和Java一致
  • Java的<? extends T> 相当于 Kotlin的 ,Java的<? super T> 相当于 Kotlin的
  • 只能生产(出参), 只能消费(入参)
  • 只能生产的原因是编译器无法确认什么对象符合那个未知的 T 的子类型,只知道一定返回T, 只能消费的原因是无法确认T超类的具体类型
  • <>相当于java中的无泛型。对于 Foo ,其中 T 是一个具有上界的协变类型参数,Foo <> 等价于 Foo ;对于 Foo ,其中 T 是一个逆变类型参数,Foo <*> 等价于 Foo
  • 先看下面的代码

class Book<in T>{
    fun getType(a:T) {
    }

    fun getName() {
        
    }
}
open class Bar<out T> {
    fun getType():T?{
        return null
    }
}

fun getType(a: Bar<*>,b:Book<*>) {
    val c = a.getType()
    c.toString()// 这个时候c是Any的类型
    b.getName()
    b.getType( )//错误 ,括号里面无论传什么都是错的,也就是会所b的getType函数是不能使用的
}

在结合泛型文档,就应该很快明白了。