泛型
泛型的使用是為了程序有更好的擴(kuò)展性萧落。
泛型類和泛型方法
class MyClass<T> {
fun <T>method(param:T):T{
return param
}
}
泛型的高級(jí)特性
java的泛型是通過(guò)類型擦除機(jī)制來(lái)實(shí)現(xiàn)的践美,什么事類型擦除機(jī)制洗贰,就是說(shuō)泛型對(duì)于類型的約束只在編譯時(shí)期存在找岖,運(yùn)行時(shí),JVM是識(shí)別不了我們?cè)诖a中指定的泛型類型的敛滋。
泛型實(shí)化
Kotlin也是基于JVM上的語(yǔ)言许布,所以同樣存在類型擦除機(jī)制。但是Kotlin中有一個(gè)內(nèi)聯(lián)函數(shù)绎晃,這個(gè)是用代碼替換的方式的原理實(shí)現(xiàn)的蜜唾,所以避免了類型擦除機(jī)制,從而可以通過(guò)T::class.java來(lái)知道泛型是具體什么類型的庶艾。這里有個(gè)泛型實(shí)化必須添加的關(guān)鍵字reified
inline fun <reified T> getGenericType()=T::class.java
fun main(){
val result1= getGenericType<String>()
val result2= getGenericType<Int>()
println(result1)
println(result2)
}
泛型實(shí)化的應(yīng)用
inline fun <reified T>startActivity(context: Context){
val intent=Intent(context,T::class.java)
context.startActivity(intent)
}
inline fun <reified T>startActivity(context: Context,block:Intent.()->Unit){
val intent=Intent(context,T::class.java)
intent.block()
context.startActivity(intent)
}
startActivity<TestActivity>(this)
startActivity<TestActivity>(this){
putExtra("param1","1")
putExtra("param2","2")
}
泛型的協(xié)變
官方一點(diǎn)的描述袁余,A是B的子類型,MyClass<A>又是MyClass<B>的子類型咱揍。那么我們就可以稱MyClass在T這個(gè)泛型上是協(xié)變的颖榜。
通俗的話來(lái)說(shuō)MyClass中的數(shù)據(jù)是只讀就可以避免類型轉(zhuǎn)換異常,比如下面這個(gè)方法煤裙,只有g(shù)et方法掩完,并且只能通過(guò)構(gòu)造函數(shù)來(lái)設(shè)置初始化值。注意關(guān)鍵字out
class SimpleData<out T>(val data:T){
fun get():T{
return data
}
}
協(xié)變?cè)趉otlin中的應(yīng)用就是List
泛型的逆變
官方描述:A是B的子類型硼砰,MyClass<B>又是MyClass<A>的子類型且蓬,那么我們稱MyClass在T這個(gè)泛型上是逆變的
用通俗的話來(lái)說(shuō)A里面的屬性就是B里面的屬性,規(guī)定了不會(huì)類型轉(zhuǎn)換異常,注意關(guān)鍵字in這個(gè)和協(xié)變是相反的题翰。
interface Transformer<in T>{
fun transform(t:T):String
}
委托
類委托
簡(jiǎn)單來(lái)說(shuō)就是自己寫(xiě)的類恶阴,里面的一些方法在別的類已經(jīng)有現(xiàn)成的寫(xiě)好了诈胜,直接用他的方法就可以了。和繼承還有點(diǎn)點(diǎn)區(qū)別存淫,委托只是取自己想要的方法就可以了耘斩。
class Myset<T>(val hashSet: HashSet<T>):Set<T>{
override val size: Int
get() = hashSet.size
override fun contains(element: T): Boolean {
return hashSet.contains(element)
}
override fun containsAll(elements: Collection<T>): Boolean {
return hashSet.containsAll(elements)
}
override fun isEmpty(): Boolean {
return hashSet.isEmpty()
}
override fun iterator(): Iterator<T> {
return hashSet.iterator()
}
}
這就是把MySet的實(shí)現(xiàn)方法交給了HashSet的對(duì)象來(lái)實(shí)現(xiàn)了,自己沒(méi)有具體的實(shí)現(xiàn)方法桅咆,這個(gè)就是委托括授。
優(yōu)化,每次都要寫(xiě)這種格式化的轉(zhuǎn)接方法比較麻煩岩饼,kotlin提供了by關(guān)鍵字荚虚。具體實(shí)現(xiàn)如下,這就代表了上面這段代碼籍茧。
class MySet2<T>(val hashSet: HashSet<T>):Set<T>by hashSet
屬性委托
lazy函數(shù)