泛型
泛型的使用是为了程序有更好的扩展性。
泛型类和泛型方法
class MyClass<T> {
fun <T>method(param:T):T{
return param
}
}
泛型的高级特性
java的泛型是通过类型擦除机制来实现的,什么事类型擦除机制,就是说泛型对于类型的约束只在编译时期存在,运行时,JVM是识别不了我们在代码中指定的泛型类型的。
泛型实化
Kotlin也是基于JVM上的语言,所以同样存在类型擦除机制。但是Kotlin中有一个内联函数,这个是用代码替换的方式的原理实现的,所以避免了类型擦除机制,从而可以通过T::class.java来知道泛型是具体什么类型的。这里有个泛型实化必须添加的关键字reified
inline fun <reified T> getGenericType()=T::class.java
fun main(){
val result1= getGenericType<String>()
val result2= getGenericType<Int>()
println(result1)
println(result2)
}
泛型实化的应用
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")
}
泛型的协变
官方一点的描述,A是B的子类型,MyClass<A>又是MyClass<B>的子类型。那么我们就可以称MyClass在T这个泛型上是协变的。
通俗的话来说MyClass中的数据是只读就可以避免类型转换异常,比如下面这个方法,只有get方法,并且只能通过构造函数来设置初始化值。注意关键字out
class SimpleData<out T>(val data:T){
fun get():T{
return data
}
}
协变在kotlin中的应用就是List
泛型的逆变
官方描述:A是B的子类型,MyClass<B>又是MyClass<A>的子类型,那么我们称MyClass在T这个泛型上是逆变的
用通俗的话来说A里面的属性就是B里面的属性,规定了不会类型转换异常,注意关键字in这个和协变是相反的。
interface Transformer<in T>{
fun transform(t:T):String
}
委托
类委托
简单来说就是自己写的类,里面的一些方法在别的类已经有现成的写好了,直接用他的方法就可以了。和继承还有点点区别,委托只是取自己想要的方法就可以了。
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的实现方法交给了HashSet的对象来实现了,自己没有具体的实现方法,这个就是委托。
优化,每次都要写这种格式化的转接方法比较麻烦,kotlin提供了by关键字。具体实现如下,这就代表了上面这段代码。
class MySet2<T>(val hashSet: HashSet<T>):Set<T>by hashSet
属性委托
lazy函数