小林のイン-アウト型変異



あなたがKotlinでジェネリックを定義するならば、あなたは何度も気がつくでしょう、それはINかoutKeyを使用するのを提案するでしょう.それは私が使用されているときに起動し、何のためのパズル
正式には、これは違反と共変を定義する方法です.私はそれについて学ぶのにしばらくかかりました、私がどのように理解して、彼らの異なっているかについて説明するために、ここで飛び込みます.

イン&アウト簡単に記憶


アウト(共変型)


ジェネリッククラスがその関数の出力としてジェネリック型を使用している場合は、outを使用します.
interface Production<out T> {
    fun produce(): T
}
主にジェネリック型の出力を生成するために、それを生産クラス/インタフェースと呼びます.したがって、非常に単純な1つ覚えて
出力=出力

対照的なもの


あなたのジェネリッククラスがそれの関数/sの入力としてジェネリック型を使用する場合、INが使用されます.
interface Consumer<in T> {
    fun consume(item: T)
}
一般的なタイプを消費しているので、私はそれを消費者クラス/インターフェースと呼びます.したがって、非常に単純な1つ覚えて
で消費する

不変タイプ


このイベントでは、1つのジェネリッククラスがジェネリック型を入力として出力し、関数に出力します.
interface ProductionConsumer<T> {
    fun produce(): T
    fun consume(item: T)
}

なぜアウトを使用しますか?


さて、今すぐ簡単に覚えているときにinandoutisは、何が重要ですか?そこに行く前に、バーガークラスオブジェクトを定義しましょう.それはファーストフードです.
単純なクラス階層

open class Food
open class FastFood : Food() 
class Burger : FastFood()

バーガー生産


上で定義された一般的な生産インターフェースを見て、さらに以下のように製品食物、ファーストフードとバーガーに彼らを広げましょう
class FoodStore : Production<Food> {
    override fun produce(): Food {
        println("Produce food")
        return Food()
    }
}

class FastFoodStore : Production<FastFood> {
    override fun produce(): FastFood {
        println("Produce food")
        return FastFood()
    }
}

class InOutBurger : Production<Burger> {
    override fun produce(): Burger {
        println("Produce burger")
        return Burger()
    }
}
今、食品製造所持者を持つことができます、我々はそれにすべてを割り当てることができます
val production1 : Production<Food> = FoodStore()
val production2 : Production<Food> = FastFoodStore()
val production3 : Production<Food> = InOutBurger()
バーガーやファーストフードの生産は、まだ食品生産です.Hence

For 'out' generic, we could assign a class of subtype to class of super-type
If we change to below, it would error out, because food or fastFood is not just a burger production.


val production1 : Production<Burger> = FoodStore()  // Error
val production2 : Production<Burger> = FastFoodStore()  // Error
val production3 : Production<Burger> = InOutBurger()

バーガーコンシューマー


さて、上で定義された一般的なコンシューマー・インターフェースを見て、以下を食物、ファストフードとバーガーを消費するためにさらに彼らを広げましょう
class Everybody : Consumer<Food> {
    override fun consume(item: Food) {
        println("Eat food")
    }
}

class ModernPeople : Consumer<FastFood> {
    override fun consume(item: FastFood) {
        println("Eat fast food")
    }
}

class American : Consumer<Burger> {
    override fun consume(item: Burger) {
        println("Eat burger")
    }
}
今、バーガーの消費者の所有者を持つことができます、我々はそれにすべてのそれらを割り当てることができます
val consumer1 : Consumer<Burger> = Everybody()
val consumer2 : Consumer<Burger> = ModernPeople()
val consumer3 : Consumer<Burger> = American()
ここでは、バーガーコンシューマーは、すべての一部である現代人の一部であるアメリカ人です.Hence

For ‘in' generic, we could assign a class of super-type to class of subtype
If we change to below,it would error out,because consumer of Food althought could be American or ModernPeople,it is not just American or just ModernPeople .


val consumer1 : Consumer<Food> = Everybody()
val consumer2 : Consumer<Food> = ModernPeople()  // Error
val consumer3 : Consumer<Food> = American()  // Error

覚えているもう一つの方法


上記を考えれば、何を使うべきか知っている

SuperType could be assigned subtype, use IN
SubType could be assigned to SuperType, use OUT



from > In and out type variant of Kotlin