简单泛型
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) //不会报错。
-
由上述代码可以看出,
? extends T
是可取不可存的——入参中只要出现T类型的函数,都不可被访问。 -
? 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); //在存值时不会有影响。
- 由上述代码可以看出,
? super T
是可存不可取——返回值中是T类型的函数,都不可被访问。
PECS原则:
- 频繁往外读取内容的,适合用上界Extends。
- 经常往里插入的,适合用下界Super
kotlin中使用 in
、 out
、*
表示 通配符边界
当我们表示一个受限制的类型时,我们称它为类型投影
, 它只能用于对类与接口的声明
。所谓投影
,可以理解是实际类型对泛型类型的映射
, 而严格的限制带来了带来安全性:
-
in T
代表只支持入参
,T类型作为类型的下界,例:
Array<in String>
对应于 Java 的Array<? super String>
可以接受CharSequence
类型或者Object
类型 -
out T
代表只支持出参
,T类型作为类型的上界
例:Array<out Number>
对应于 Java 的Array<? extends Number>
可以接受Integer
类型或者Double
类型 。
当我们不希望对出参、入参进行限制,只希望所有具体的实例化都是该泛型的子类。(还记得ArrayList<String> 不是ArrayList<Object>的子类吗),Kotlin提供了*投影
解决此问题
-
*投影
可以不受类型的限制,对于<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"
}
网友评论