8.1、泛型的基本概念
函数申明泛型
inline fun <T> maxOf(a: T, b: T): T{ }
类申明泛型
class MyTest<T> {
}
8.2、泛型的约束
1、添加类型约束
要求T可以比较大小
inline fun <T : Comparable<T>> maxOf(a: T, b: T): T {
return if (a > b) a else b
}
2、添加多个类型约束
进一步:要求T可以比较大小同时是一个函数
inline fun <T> callMax(a: T, b: T)
where T : Comparable<T>, T : () -> Unit {
return if (a > b) a() else b()
}
3、多个泛型参数
inline fun <T, R> callMax(a: T, b: T): R
where T : Comparable<T>, T : () -> R, R : Number {
return if (a > b) a() else b()
}
多个泛型参数的例子
K是Serializable类型,V是Comparable类型
class Map<K,V> where K:Serializable,V:Comparable<V>
8.3、泛型的型变
定义
例子1
首先看一个泛型的例子
class MainActivity2 : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main2)
var array1: Array<B> = arrayOf(B(), B(), B())
val array2: Array<A> = array1
}
}
open class A
class B : A()
发现发现 val array2: Array = array1会有提示错误 Type mismatch. Required:Array Found:Array,Array并不是Array的子类,因为kotlin中的泛型默认是不型变的,无法完成类型转换,但是B是A的子类,但是这个赋值理论上是合理的,安全的。
那么我们如何解决这个问题呢?
class MainActivity2 : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main2)
var array1: Array<B> = arrayOf(B(), B(), B())
val array2: Array<out A> = array1
}
}
open class A
class B : A()
当类或接口的泛型参数被声明为out时,则该类型参数是协变的。
****好处是:**A**是**B**的父类,那么**List<A>**可以是**List<B>**的父类。***
例子2
我们看另外的一个泛型的例子
class MainActivity2 : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main2)
var array1: Array<A> = arrayOf(A(), A(), A())
val array2: Array<B> = array1
}
}
open class A
class B : A()
发现 val array2: Array = array1 会有提示错误:Type mismatch. Required: Array Found: Array ,Array 并不是Array的子类,针对这种情况,该怎么办呢?
class MainActivity2 : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main2)
var array1: Array<A> = arrayOf(A(), A(), A())
val array2: Array<in B> = array1
}
}
open class A
class B : A()
当类或接口的泛型参数被声明为in时,则该类型参数是逆变的。
好处是:**A**是**B**的父类,那么**List<B>**可以是**List<A>**的父类。
逆变的理解?
比如Number是父类,Int是子类
但是Comparable 是子类,Comparable 是父类
逆变可以这么理解:他们的关系发生了转换,如果一个数是Int,那么这个数就是Number
如果可以比较Number,那么一定可以比较Int,这种关系居然发生了变化。
new