Kotlin泛型的高級特性

Kotlin中是可以將內聯函數中的泛型進行實化的。
那麼具體該怎麼寫才能將泛型實化呢?首先,該函數必須是內聯函數纔行,也就是要用inline
關鍵字來修飾該函數。其次,在聲明泛型的地方必須加上reified關鍵字來表示該泛型要進行
實化。

inline fun <reified T> getGenericType() {
}

getGenericType()函數直接返回了當前指定泛型的實際類型。T.class這樣的語法在Java
中是不合法的,而在Kotlin中,藉助泛型實化功能就可以使用T::class.java這樣的語法了。

inline fun <reified T> getGenericType() = T::class.java
fun main() {
val result1 = getGenericType<String>()
val result2 = getGenericType<Int>()
println("result1 is $result1")
println("result2 is $result2")
}

運行結果:
result1 is class java.lang.String
result2 is class java.lang.Integer

Android中的實際用法:

inline fun <reified T> startActivity(context: Context) {
	val intent = Intent(context, T::class.java)
	context.startActivity(intent)
}

startActivity<TestActivity>(context)

泛型的協變

參數列表是接收數據的地方,因此可以稱它爲in位置
返回值是輸出數據的地方,因此可以稱它爲out位置
image
定義了一個MyClass<T>的泛型類,其中A是B的子類型,同時 MyClass<A> 又是 MyClass<B> 的子類型,那麼我們就可以稱MyClass在T這個泛型上是協變的。

在泛型T的聲明前面加上了一個out關鍵字。這就意味着現在T只能出現在out位置上,而不能出現在in位置上,同時也意味着SimpleData在泛型T上是協變的。

open class Person(val name: String, val age: Int)
class Student(name: String, age: Int) : Person(name, age)
class Teacher(name: String, age: Int) : Person(name, age)

class SimpleData<out T>(val data: T?) {
fun get(): T? {
	return data
}
}

fun main() {
	val student = Student("Tom", 19)
	val data = SimpleData<Student>(student)
	handleMyData(data)
	val studentData = data.get()
	println(studentData?.name)
	println(studentData?.age)
	}
	fun handleMyData(data: SimpleData<Person>) {
		val personData = data.get()
	}

泛型的逆變

泛型在協變時只出現在out位置上,逆變時只出現在in位置上,就不會存在類型轉換異常的情況

interface Comparable<in T> {
operator fun compareTo(other: T): Int
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章