0Pricing
Kotlin Academy · レッスン

使用側変性

型プロジェクションを学びます

「使用側変性」はCoddyKit上の無料Kotlin Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはKotlin Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Kotlin Academyコースには全4レッスンが含まれています。

使用側変性

ジェネリッククラス全体は不変でも、特定の関数だけがその型を生成したり消費したりすることがあります。使用側変性(型プロジェクション)では、型を使う場所でoutまたはinを適用します。

使用側変性を使う理由

MutableList<T>のような不変クラスは、Tの読み取りと書き込みの両方を行うため、宣言時に共変にはできません。しかし、特定の関数がそのリストから読み取るだけなら、プロジェクションを使って安全にそれを表現できます。

out プロジェクション

パラメーターの型にArray<out T>と記述すると、共変なビューになります。Tを読み取ることはできますが、書き込むことはできません。これにより、Array<String>をArray<out Any>が期待される場所に渡せます。

fun printArray(items: Array<out Any>) {
    for (item in items) println(item)
}

fun main() {
    val names: Array<String> = arrayOf("Ann", "Bob")
    printArray(names)
}

読み取り専用

outプロジェクションでは、コンパイラーは読み取り(出力)を許可しますが、書き込み(入力)は禁止します。書き込みを許可すると、元の配列の型安全性を損なう可能性があるためです。

in プロジェクション

Array<in T>と記述すると、反変なビューになります。Tをそこへ書き込めますが、読み取った値はAny?として返されます。これにより、Tまたはそのスーパータイプの配列を受け取れます。

fun fill(dest: Array<in Int>, value: Int) {
    for (i in dest.indices) dest[i] = value
}

fun main() {
    val numbers: Array<Number> = arrayOf(0, 0, 0)
    fill(numbers, 7)
    println(numbers.toList())
}

書き込み専用

inプロジェクションでは、Tの値を書き込むこと(入力)はできますが、要素の型は読み取り時に最上位型として扱われます。実際の要素型が任意のスーパータイプである可能性があるためです。

使用側変性と宣言側変性

宣言側変性(class Box<out T>)は、そのクラスを使うすべての場所に適用されます。使用側プロジェクション(パラメーターとしてのBox<out T>)は、その1か所にだけ適用されます。クラス自体を不変のままにする必要がある場合に、プロジェクションを使います。

スター射影

型引数をまったく気にしない場合は、スター射影 *を使用します。List<*>は、型が不明な何らかの型のリストを意味します。要素は上限境界として読み取れますが、安全に書き込むことはできません。

fun printSize(collection: List<*>) {
    println("Size: ${collection.size}")
}

fun main() {
    printSize(listOf(1, 2, 3))
    printSize(listOf("a", "b"))
}

スター射影の制限

*を使用しても、sizeのような型に依存しないメンバーは呼び出せます。また、要素をAny?として読み取ることもできますが、実際の型が不明なため要素を追加することはできません。

fun main() {
    val unknown: List<*> = listOf("x", "y")
    val first: Any? = unknown.first()
    println(first)
}

射影の選択

関数が読み取りだけを行う場合はout Tを、書き込みだけを行う場合はin Tを、正確な型が重要でない場合は*を使用します。これらの射影により、不変なクラスを柔軟かつ型安全な方法で利用できます。

Javaのワイルドカードとの関係

Kotlinのout Tおよびin Tの射影は、Javaの? extends Tおよび? super Tのワイルドカードに対応します。Javaのジェネリクスを知っていれば、射影にもすぐに慣れるでしょう。

理解度チェック

Array<out Any>型のパラメータでは、何ができますか?

まとめ

使用箇所変性では、特定の使用箇所でout(読み取り専用)またはin(書き込み専用)の射影を適用し、型が不明な場合は*をスター射影として使用します。これにより、宣言を変更せずに不変なクラスを柔軟に利用できます。次は、ジェネリック制約を使って型パラメータを制限します。

よくある質問

「使用側変性」レッスンは無料ですか?

はい。「使用側変性」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Kotlin Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Kotlin Academyコースには全4レッスンが含まれています。

「使用側変性」で何を学びますか?

型プロジェクションを学びます ブラウザで直接実行するハンズオンコードでKotlin Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Kotlin Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのKotlin Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「使用側変性」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このKotlin Academyレッスンでコードを書いて実行できますか?

はい。すべてのKotlin Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. ジェネリック関数とクラス
  2. 宣言側変性
  3. 使用側変性
  4. ジェネリック制約
← Kotlin Academyに戻る