Kotlin学習ノート(九)【汎用】

6379 ワード

Kotlin汎用
汎用型、すなわち「パラメータ化タイプ」は、タイプをパラメータ化し、クラス、インタフェース、メソッドに使用できます.Javaと同様に、Kotlinも汎用型を提供し、タイプの安全を保証し、タイプの強転の悩みを解消します.汎用クラスを宣言します.
class Box<T>(t: T) {
    var value = t
}

クラスのインスタンスを作成するには、タイプパラメータを指定する必要があります.
val box: Box = Box(1)
//   
val box = Box(1) //           ,1    Int,             Box

次の例では、汎用クラスBoxに整数データと文字列を入力します.
fun main(args: Array) {
    val boxInt: Box = Box(1)
    val boxString: Box = Box("qfxl")
    println(boxInt.value)
    println(boxString.value)
}

class Box(t: T) {
    var value = t
}

出力結果:1 qfxl
汎用タイプ変数を定義し、タイプパラメータを完全に明記したり、コンパイラがタイプパラメータを自動的に推定したり、タイプパラメータを省略したりすることができます.Kotlin汎用関数の宣言はJavaと同じで、タイプパラメータは関数名の前に配置します.
fun main(args: Array) {
    val boxInt = boxIn(1)
    val boxString = boxIn("qfxl") //     String
    println(boxInt.value)
    println(boxString.value)
}

class Box<T>(t: T) {
    var value = t
}

fun  boxIn(t: T) = Box(t)

出力結果:1 qfxl
汎用関数を呼び出す場合、タイプパラメータを推定できる場合は、汎用パラメータを省略できます.次の例では、入力された異なるタイプに応じて対応する汎用関数doPrintが作成されます.
fun main(args: Array) {
    val name = "qfxl"
    val age = 26
    val bo = false

    doPrint(name)
    doPrint(age)
    doPrint(bo)
}

fun  doPrint(t: T) {
    when (t) {
        is String -> println("T is String upperCase is ${t.toUpperCase()}")
        is Int -> println("T is Int value is $t")
        else -> println("T is not String or Int")
    }
}

出力結果:
T is String upperCase is QFXL T is Int value is 26 T is not String or Int
汎用拘束
汎用コンストレイントを使用して、所定のパラメータで使用できるタイプを設定できます.Kotlinで使用:汎用タイプの上限を拘束します.最も一般的な制約は上界(upper bound):
fun > sort(list: List) {
    // ……
}

ComparableのサブタイプはTに取って代わることができる.例:
sort(listOf(1, 2, 3)) // OK。Int   Comparable     
sort(listOf(HashMap())) //   :HashMap    Comparable>     

デフォルトの上界はAny?です.複数の上界コンストレイントの場合、where句を使用します.
fun <T> cloneWhenGreater(list: List<T>, threshold: T): List<T>
    where T : Comparable, Cloneable {
      return list.filter(it > threshold).map(it.clone())
    }

ひずみ
Kotlinにはワイルドカードタイプはなく、宣言箇所型変(declaration-site variance)とタイプ投影(type projections)の2つの他のものがあります.
宣言のタイプ変異は、コヒーレント注釈修飾子:in、out、消費者in、生産者outを使用します.
コヒーレンス(covariant:Foo=Foo)
協変は親類の汎用型から具体的なサブクラスに変わり、KotlinはJava中のinのワイルドカード文法の代わりに extends E>のキーワードを提供し、同時にJava中の汎用型の消去中に発生したタイプ変換の安全を解決するために、KotlinはC#の戦略を採用した.すなわち、協変型は消費者として、読み取るしかなく書き込むことができない.outを使用して、1つのタイプのパラメータをコヒーレントにします.コヒーレントタイプのパラメータは出力としてのみ使用できます.戻り値のタイプとして使用できますが、パラメータのタイプとして使用できません.
//           
class Runoob(val a: A) {
    fun foo(): A {
        return a
    }
}

fun main(args: Array<String>) {
    var strCo: Runoob<String> = Runoob("a")
    var anyCo: Runoob = Runoob("b")
    anyCo = strCo
    println(anyCo.foo())   //    a
}

**逆変換(contravariance:Foo=Foo)逆変換サブタイプ型が特定の親になり、KotlinはJavaの代わりにoutキーを提供します.