泛型、型变与投影

简单泛型

kotlin 对于简单泛型的支持与java类似, 可以通过通配符,提升代码的灵活度

data class Response<T>(val code: Int, var body: T) { }/定义了一个泛型类

限定型泛型

在编码实践中,通常来说只使用简单的通配符来增加自由度,我们也需要用到限定性泛型,可以通过where关键字来约束自由度

interface callback<in T> 
       where T : Response<Any> { //T 必须是Response类型
   fun onSuccess(response: T)
   fun onFailed()
}

泛型的通配符边界

先说明一个java 中泛型的通配符边界的预备知识:

1 . ? extends T叫做上界通配符,用来表示所有T类型及其子类型。例如List<? extends Number>List<Integer>的超类。

ArrayList<? extends Number> list=new ArrayList<Integer>(); //  ? extends Number :可以接收所有Number的子类

list.add(Integer(1));  //会报错,因为编译器并无法了解该超类(? extends Number)泛型的实现类(Integer)的类型。

Number number=list.get(0) //不会报错。
  1. 由上述代码可以看出, ? extends T是可取不可存的——入参中只要出现T类型的函数,都不可被访问。

  2. ? super T叫做下界通配符,用阿里表示所有T类型及其超类。例如List<? super Number>List<Object>的超类,

ArrayList<? super Integer> list=new ArrayList<Object>();
Object a= list.get(0)  //? super 在取值时只能是Object
list.add(1); //在存值时不会有影响。
  1. 由上述代码可以看出, ? super T是可存不可取——返回值中是T类型的函数,都不可被访问。
PECS原则:
  - 频繁往外读取内容的,适合用上界Extends。
  - 经常往里插入的,适合用下界Super

kotlin中使用 inout*表示 通配符边界

当我们表示一个受限制的类型时,我们称它为类型投影, 它只能用于对类与接口的声明。所谓投影,可以理解是实际类型对泛型类型的映射, 而严格的限制带来了带来安全性:

  1. in T 代表只支持入参,T类型作为类型的下界,

    Array<in String>对应于 Java 的 Array<? super String>可以接受 CharSequence 类型或者 Object 类型

  2. out T 代表只支持出参,T类型作为类型的上界
    Array<out Number>对应于 Java 的 Array<? extends Number>可以接受 Integer 类型或者 Double 类型 。

当我们不希望对出参、入参进行限制,只希望所有具体的实例化都是该泛型的子类。(还记得ArrayList<String> 不是ArrayList<Object>的子类吗),Kotlin提供了*投影解决此问题

  1. *投影 可以不受类型的限制,对于<out T>来说,*投影 相当于<out Any>; 而对于<in T>来说,*投影相当于<in Nothing>

    // TODO

简单泛型的扩展

kotlin支持针对泛型的扩展,比如给每个Logger添加一个code解析方法:

interface logger {
    fun log(tag: String, value: String)
}

class MyLogger : logger {
    override fun log(tag: String, value: String) {
        System.out.println("$tag  do $value")  
    }
}

fun <T> T.write(text: String): Unit where  T : logger { //针对所有logger添加扩展
    this.log("test", "write $text") 
}

fun main(args: Array<String>) {
    var log: MyLogger = MyLogger()
    log.write("doulala") //print  "test  do write doulala"
}
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 前言 人生苦多,快来 Kotlin ,快速学习Kotlin! 什么是Kotlin? Kotlin 是种静态类型编程...
    任半生嚣狂阅读 26,491评论 9 118
  • 前言 泛型(Generics)的型变是Java中比较难以理解和使用的部分,“神秘”的通配符,让我看了几遍《Java...
    珞泽珈群阅读 12,403评论 12 51
  • 第8章 泛型 通常情况的类和函数,我们只需要使用具体的类型即可:要么是基本类型,要么是自定义的类。但是在集合类的场...
    光剑书架上的书阅读 6,394评论 6 10
  • 标签: Kotlin 本文声明:本文由Coder-pig编写,想了解其他内容,可见【Coder-Pig的猪栏】尊重...
    coder_pig阅读 3,818评论 3 3
  • 互联网发展至今,经历了几个划时代的产物,2000年前后, 新浪、搜狐作为中国第一代互联网的门户席卷了中国大地;20...
    bigParis阅读 2,999评论 0 1

友情链接更多精彩内容