← Back to Kotlin Course | Chapter 11: Generics | Lesson 3 of 6

Variance: in और out

in और out Kotlin को बताते हैं कि क्या कोई generic placeholder सिर्फ कभी प्राप्त होगा, सिर्फ कभी दिया जाएगा, या दोनों, ताकि यह सुरक्षित substitutions की अनुमति दे सके।
Syntax
kotlin
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

markup
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)
}

Covariance with out

किसी type parameter को out चिह्नित करना किसी Producer<Sub> को वहां उपयोग करने देता है जहां एक Producer<Super> की उम्मीद हो, क्योंकि type सिर्फ produce (return) होने वाली चीज़ के रूप में दिखाई देता है, जो हमेशा सुरक्षित है।

उदाहरण: Covariance with out

markup
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)
}

Contravariance with in

किसी type parameter को in चिह्नित करना किसी Consumer<Super> को वहां उपयोग करने देता है जहां एक Consumer<Sub> की उम्मीद हो, क्योंकि type सिर्फ accept (एक parameter) होने वाली चीज़ के रूप में दिखाई देता है, जो विपरीत दिशा में सुरक्षित है।

उदाहरण: Contravariance with in

markup
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)
}

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>

markup
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)
}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
आम गलतियां
  1. किसी invariant generic type का उपयोग करना जहां एक covariant (out) या contravariant (in) अब भी सुरक्षित रहते हुए ज़्यादा flexible code की अनुमति देता।
  2. किसी type parameter को out चिह्नित करना और फिर इसे किसी function parameter type के रूप में उपयोग करने की कोशिश करना, जिसे compiler मना करता है क्योंकि out type को सिर्फ output positions तक सीमित करता है।
  3. 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:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.