在Kotlin中,協變和逆變是泛型編程中的兩個重要概念,它們允許我們在類型系統中更加靈活地處理類型關系。
1.協變:協變允許我們使用比原始類型更具體的類型。在kotlin中,通過在類型參數上加out關鍵字來表示協變,生產者,例如,如果我們有一個泛型類List,其中T是一個協變類型參數,那么我們可以將List賦值給List,因為String是Any的子類型。
2.逆變:逆變允許我們使用比原始類型更一般的類型。在kotlin中,通過在類型參數上加in關鍵字來表示逆變,消費者,例如,如果我們有一個泛型函數fun foo(list: List),其中T是一個逆變類型參數,那么我們可以將List傳遞給foo函數,因為Any是String的超類型。
協變代碼舉例:
interface Producer<out T> {//協變 out 類似java中的 extendfun produce(): T
}
open class Fruit
open class Apple: Fruit()class FruitProducer:Producer<Fruit> {override fun produce(): Fruit {return Fruit()}
}class AppleProducer:Producer<Apple> {override fun produce(): Apple {return Apple()}
}fun <T> processProduce(producer:Producer<T>) {val product = producer.produce()println(product)
}fun main(){var fruitProducer:Producer<Fruit> = FruitProducer()var appleProducer:Producer<Apple> = AppleProducer()processProduce(fruitProducer)processProduce(appleProducer)
// appleProducer = fruitProducer //報錯,協變,不允許將Producer<Fruit>賦值給Producer<Apple>
// fruitProducer = appleProducer //協變,允許將Producer<Apple>賦值給Producer<Fruit>}
逆變代碼舉例:
interface Consumer<in T>{ //逆變 in 類似java中的superfun consume()
}class FruitConsumer:Consumer<Fruit>{override fun consume() {println("consume fruit")}
}class AppleConsumer:Consumer<Apple>{override fun consume() {println("consume apple")}
}inline fun <T> processConsumer(consumer:Consumer<T>){consumer.consume()
}fun main() {var fruitConsumer:Consumer<Fruit> = FruitConsumer()var appleConsumer:Consumer<Apple> = AppleConsumer()processConsumer(fruitConsumer)processConsumer(appleConsumer)
// fruitConsumer = appleConsumer //報錯,逆變,不允許將Consumer<Apple>賦值給Consumer<Fruit>
// appleConsumer = fruitConsumer //允許將Consumer<Fruit>賦值給Consumer<Apple>,}