Kotlin 泛型 型变、逆变、星号投影、reified、泛型上限

1. kotlin 定义泛型类


// 定义泛型类
open class GenericDemo<T>(open var field: T? = null)

// 继承泛型类
class SubGeneric(param: Float) : GenericDemo<Float>() {
    
    
    override var field: Float? = param
}

fun main() {
    
    
 	val demo1 = GenericDemo<String>("demo1")
    val demo2 = GenericDemo<Int>(2)
    val demo3 = GenericDemo(true)
    val demo4 = SubGeneric(3.14f)

    println("${
      
      demo1.field}, ${
      
      demo2.field}, ${
      
      demo3.field}, ${
      
      demo4.field}") // demo1, 2, true, 3.14
}


2. kotlin 定义类型变

kotlin 使用 out 定义型变。即向外提供的类型,不能向其写入,同 java 的通配符上限


// name 只能用 val 声明,否则会有 setter 方法向其写入
class Fruit<out T>(private val name: T) {
    
    
    fun getFruitName(): T {
    
    
        return name
    }
}

fun main() {
    
    
	val apple = Fruit("apple")
	
	// Fruit<String> 可以被赋值给 Fruit<Any>
	val fruit: Fruit<Any> = apple
	println(fruit.getFruitName())
}


3. kotlin 定义类逆变

kotlin 使用 in 定义逆变。即向里写入的类型,不能向外提供,同 java 通配符下限


class Reverse<in T> {
    
    
    fun setValue(value: T) {
    
    
        println("value: $value")
    }
}

fun main() {
    
    
	var reverse1 = Reverse<Int>()
	val reverse2 = Reverse<Number>()
	reverse2.setValue(3.14f) // value: 3.14
	
	// 可以将 Reverse<Number> 赋值给 Reverse<Int>
	reverse1 = reverse2
}


4. kotlin 定义调用处型变

在调用原本不支持型变的类时,如 ArrayList,可以在使用时用 out 修饰泛型支持型变


fun main() {
    
    
 	var arrNumber: ArrayList<out Number> = arrayListOf(1, 0.2, 3f)
    val arrayInt: ArrayList<Int> = arrayListOf(1, 2, 3)
    
    // arrNumber 可以接受元素为 Int 类型集合
    arrNumber = arrayInt
    println(arrNumber) // [1, 2, 3]
}


5. kotlin 定义调用处逆变

在调用原本不支持型变的类时,如 ArrayList,可以在使用时用 in 修饰泛型支持逆变


fun main() {
    
    
 	var arrInt: ArrayList<in Int> = arrayListOf(1, 2, 3)
    val arrNum: ArrayList<Number> = arrayListOf(1, 0.2, 3f)
    
    // arrInt 可以接受元素为 Number 类型集合
    arrInt = arrNum
    println(arrInt) // [1, 0.2, 3.0]
}


6. kotlin 星号投影


fun main() {
    
    
	// val list : ArrayList = arrayListOf(1, 2, 3) // 编译错误
    // 使用 * 号,等价于 out Any? 可接受任意类型的元素
    val list1: ArrayList<*> = arrayListOf(1, 0.2, "3")
    val list2: ArrayList<out Any?> = arrayListOf(1, 0.2, "3")
    println("list1: $list1, list2: $list2") // list1: [1, 0.2, 3], list2: [1, 0.2, 3]
}


7. kotlin 定义泛型函数


fun <T> printSelf(param: T) {
    
    
    println(param)
}  


8. kotlin 使用 reified 修饰泛型

使用 reified 修饰 泛型后,可以将泛型变成具体化的类型(泛型具型化),从而可以使用其相关方法


inline fun <reified T> printSelfName() {
    
    
    val name = T::class.simpleName
    println("class simple name: $name")
}

fun main() {
    
    
 	printSelfName<Int>() // class simple name: Int
    printSelfName<String>() // class simple name: String
}


9. kotlin 定义泛型上限


// 定义类泛型上限
class Container<T : Number>(var param: T)

// 定义方法泛型上限
fun <T : Number> sum(vararg param: T) {
    
    
    var sum = 0.0
    param.forEach {
    
    
        sum += it.toDouble()
    }
    println("求和: $sum")
}
    
fun main() {
    
    
    val c1 = Container<Int>(1)
    val c3 = Container<Long>(3L)
    val c4 = Container<Float>(3.14f)
    
	sum(1, 2f, 3.0) // 求和: 6.0
}

// 类泛型指定多个上限
class Test<T>() where T : Callable<T>, T : Runnable {
    
    }

// 方法泛型指定多个上限
fun <T> func(param: T) where T : Callable<T>, T : Runnable {
    
    }
    

附 Github 源码:

TestGeneric.kt

猜你喜欢

转载自blog.csdn.net/java_android_man/article/details/121845379