Sobes.tech
Junior

Какви видове генерични лекарства знаете?

sobes.tech AI

Отговор от AI

Инвариантни, ковариантни и контравариантни.

  • Инвариантност: Типът List<A> не е подтип на List<B> и обратното, дори ако A е подтип на B. Типът остава точно.
  • Ковариантност (out): Позволява използването на подтипове. List<A> е подтип на List<B>, ако A е подтип на B. Използва се за изходни параметри (връщани стойности).
fun foo(list: List<out Number>) {
    // Може да чете от списъка (Number, Double, Int и др.)
    val number: Number = list[0]
    // Не може да добавя към списъка (не е известно какъв тип елементите)
    // list.add(1) // Грешка при компилация
}
  • Контравариантност (in): Позволява използването на супертипове. List<B> е подтип на List<A>, ако A е подтип на B. Използва се за входни параметри (аргументи).
fun foo(comparable: Comparable<in String>) {
    // Могат да се предават аргументи от тип String (или негови супертипове)
    val result = comparable.compareTo("hello")
    // Не може да се получават резултати от тип String (не е известно какъв е резултатът)
    // val str: String = comparable.compareTo("world") // Грешка при компилация
}

В Kotlin тези концепции се реализират с помощта на анотациите out и in върху параметрите на тип. В Java се използват wildcards (? extends за ковариантност и ? super за контравариантност).

Тип Цел Ключова дума (Kotlin) Wildcard (Java) Четене разрешено Запис разрешен
Инвариантен Точно съвпадение на типа Не Не Да Да
Ковариантен Използване на подтипове (продуцент - "out") out ? extends T Да Не
Контравариантен Използване на супертипове (консуматор - "in") in ? super T Не Да