Variance: in और out
In this page:
class Producer<out T>(val value: T) // covariant: only produces T
class Consumer<in T> { // contravariant: only consumes T
fun consume(item: T) { }
}
The Problem Without Variance
Default रूप से, generic types invariant होते हैं, यानी Box<Dog> को अपने आप Box<Animal> नहीं माना जाता भले ही Dog, Animal का एक subtype हो, क्योंकि अन्यथा यह असंगत types को असुरक्षित रूप से डालने दे सकता था।
उदाहरण: The Problem Without Variance
open class Animal(val name: String)
// Define a class `Dog`
class Dog(name: String) : Animal(name)
// Define a class `Box`
class Box<T>(val item: T)
// Entry point: execution of the program starts here
fun main() {
// Declare a read-only variable `dogBox` (a `Box<Dog>`), set to `Box(Dog("Rex"))`
val dogBox: Box<Dog> = Box(Dog("Rex"))
// Print `dogBox.item.name` to the console, with a trailing newline
println(dogBox.item.name)
}
Login to try C/C++/Java/PHP code in the editor
Covariance with out
किसी type parameter को out चिह्नित करना किसी Producer<Sub> को वहां उपयोग करने देता है जहां एक Producer<Super> की उम्मीद हो, क्योंकि type सिर्फ produce (return) होने वाली चीज़ के रूप में दिखाई देता है, जो हमेशा सुरक्षित है।
उदाहरण: Covariance with out
open class Animal(val name: String)
// Define a class `Dog`
class Dog(name: String) : Animal(name)
// Define a class `Producer`
class Producer<out T>(private val item: T) {
// Define the function `produce` with no parameters and returning a `T`
fun produce(): T = item
}
// Define the function `printAnimalName` taking `producer`
fun printAnimalName(producer: Producer<Animal>) {
// Print `producer.produce().name` to the console, with a trailing newline
println(producer.produce().name)
}
// Entry point: execution of the program starts here
fun main() {
// Declare a read-only variable `dogProducer` (a `Producer<Dog>`), set to `Producer(Dog("Rex"))`
val dogProducer: Producer<Dog> = Producer(Dog("Rex"))
printAnimalName(dogProducer)
}
Login to try C/C++/Java/PHP code in the editor
Contravariance with in
किसी type parameter को in चिह्नित करना किसी Consumer<Super> को वहां उपयोग करने देता है जहां एक Consumer<Sub> की उम्मीद हो, क्योंकि type सिर्फ accept (एक parameter) होने वाली चीज़ के रूप में दिखाई देता है, जो विपरीत दिशा में सुरक्षित है।
उदाहरण: Contravariance with in
open class Animal(val name: String)
// Define a class `Dog`
class Dog(name: String) : Animal(name)
// Define a class `Consumer`
class Consumer<in T> {
// Define the function `consume` taking `item`
fun consume(item: T) {
// Print "Consuming an item" to the console, with a trailing newline
println("Consuming an item")
}
}
// Define the function `feedDog` taking `consumer`
fun feedDog(consumer: Consumer<Dog>) {
consumer.consume(Dog("Rex"))
}
// Entry point: execution of the program starts here
fun main() {
// Declare a read-only variable `animalConsumer` (a `Consumer<Animal>`), set to `Consumer()`
val animalConsumer: Consumer<Animal> = Consumer()
feedDog(animalConsumer)
}
Login to try C/C++/Java/PHP code in the editor
Kotlin's Built-in List<out T>
standard library का read-only List<out T> covariant declared है, यही वजह है कि एक List<Dog> को सीधे वहां पास किया जा सकता है जहां एक List<Animal> की उम्मीद हो।
उदाहरण: Kotlin's Built-in List<out T>
open class Animal(val name: String)
// Define a class `Dog`
class Dog(name: String) : Animal(name)
// Define the function `printNames` taking `animals`
fun printNames(animals: List<Animal>) {
// Loop over `animals) println(animal.name`, binding each item to `animal`
for (animal in animals) println(animal.name)
}
// Entry point: execution of the program starts here
fun main() {
// Declare a read-only variable `dogs` (a `List<Dog>`), set to `listOf(Dog("Rex"), Dog("Fido"))`
val dogs: List<Dog> = listOf(Dog("Rex"), Dog("Fido"))
printNames(dogs)
}
Login to try C/C++/Java/PHP code in the editor
- किसी invariant generic type का उपयोग करना जहां एक covariant (
out) या contravariant (in) अब भी सुरक्षित रहते हुए ज़्यादा flexible code की अनुमति देता। - किसी type parameter को
outचिह्नित करना और फिर इसे किसी function parameter type के रूप में उपयोग करने की कोशिश करना, जिसे compiler मना करता है क्योंकिouttype को सिर्फ output positions तक सीमित करता है। out(covariant, producer) कोin(contravariant, consumer) के साथ confuse करना; वे विपरीत तरह के substitutions की अनुमति देते हैं।
out Tकिसी type parameter को covariant चिह्नित करता है, यानी यह सिर्फ output (return) positions में दिखाई दे सकता है, औरProducer<Sub>को वहां उपयोग होने देता है जहांProducer<Super>की उम्मीद हो।in Tकिसी type parameter को contravariant चिह्नित करता है, यानी यह सिर्फ input (parameter) positions में दिखाई दे सकता है, औरConsumer<Super>को वहां उपयोग होने देता है जहांConsumer<Sub>की उम्मीद हो।in/out(invariant) के बिना,Container<Sub>अपने आपContainer<Super>की जगह substitutable नहीं है, भले हीSubएक subtype हो।- Kotlin का built-in
List<out T>covariant है (read-only), जबकि एक काल्पनिक pure consumer interface आमतौर पर contravariant होता।
Chapter Quiz — Complete all 6 topics to unlock
0/6 topics done
Complete these topics first: