簡(jiǎn)單泛型
kotlin 對(duì)于簡(jiǎn)單泛型
的支持與java類似, 可以通過通配符
思灰,提升代碼的靈活度
data class Response<T>(val code: Int, var body: T) { }/定義了一個(gè)泛型類
限定型泛型
在編碼實(shí)踐中玷犹,通常來說只使用簡(jiǎn)單的通配符
來增加自由度,我們也需要用到限定性泛型
洒疚,可以通過where
關(guān)鍵字來約束自由度
interface callback<in T>
where T : Response<Any> { //T 必須是Response類型
fun onSuccess(response: T)
fun onFailed()
}
泛型的通配符邊界
先說明一個(gè)java 中泛型的通配符邊界
的預(yù)備知識(shí):
1 . ? extends T
叫做上界通配符
歹颓,用來表示所有T類型及其子類型坯屿。例如List<? extends Number>
是 List<Integer>
的超類。
ArrayList<? extends Number> list=new ArrayList<Integer>(); // ? extends Number :可以接收所有Number的子類
list.add(Integer(1)); //會(huì)報(bào)錯(cuò),因?yàn)榫幾g器并無法了解該超類(? extends Number)泛型的實(shí)現(xiàn)類(Integer)的類型巍扛。
Number number=list.get(0) //不會(huì)報(bào)錯(cuò)领跛。
由上述代碼可以看出,
? extends T
是可取不可存的——入?yún)⒅兄灰霈F(xiàn)T類型的函數(shù)撤奸,都不可被訪問吠昭。? super T
叫做下界通配符
,用阿里表示所有T類型及其超類胧瓜。例如List<? super Number>
是List<Object>
的超類矢棚,
ArrayList<? super Integer> list=new ArrayList<Object>();
Object a= list.get(0) //? super 在取值時(shí)只能是Object
list.add(1); //在存值時(shí)不會(huì)有影響。
- 由上述代碼可以看出府喳,
? super T
是可存不可取——返回值中是T類型的函數(shù)幻妓,都不可被訪問。
PECS原則:
- 頻繁往外讀取內(nèi)容的劫拢,適合用上界Extends肉津。
- 經(jīng)常往里插入的,適合用下界Super
kotlin中使用 in
舱沧、 out
妹沙、*
表示 通配符邊界
當(dāng)我們表示一個(gè)受限制的類型時(shí),我們稱它為類型投影
熟吏, 它只能用于對(duì)類與接口的聲明
距糖。所謂投影
,可以理解是實(shí)際類型對(duì)泛型類型的映射
, 而嚴(yán)格的限制帶來了帶來安全性:
-
in T
代表只支持入?yún)?/code>牵寺,T類型作為類型的下界悍引,
例:
Array<in String>
對(duì)應(yīng)于 Java 的Array<? super String>
可以接受CharSequence
類型或者Object
類型 out T
代表只支持出參
,T類型作為類型的上界
例:Array<out Number>
對(duì)應(yīng)于 Java 的Array<? extends Number>
可以接受Integer
類型或者Double
類型 帽氓。
當(dāng)我們不希望對(duì)出參趣斤、入?yún)⑦M(jìn)行限制,只希望所有具體的實(shí)例化都是該泛型的子類黎休。(還記得ArrayList<String> 不是ArrayList<Object>的子類嗎)浓领,Kotlin提供了*投影
解決此問題
-
*投影
可以不受類型的限制,對(duì)于<out T>
來說势腮,*投影
相當(dāng)于<out Any>
; 而對(duì)于<in T>
來說联贩,*投影
相當(dāng)于<in Nothing>
// TODO
簡(jiǎn)單泛型的擴(kuò)展
kotlin支持針對(duì)泛型的擴(kuò)展
,比如給每個(gè)Logger添加一個(gè)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 { //針對(duì)所有l(wèi)ogger添加擴(kuò)展
this.log("test", "write $text")
}
fun main(args: Array<String>) {
var log: MyLogger = MyLogger()
log.write("doulala") //print "test do write doulala"
}