Kotlin Academy · レッスン

スコープ付き拡張とcompanion拡張

拡張の可視性を制限し、companion objectに拡張を追加します。

レッスン 3/414 ステップ

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

拡張関数にスコープを設定する理由

デフォルトでは、拡張はインポートした場所であればどこでも参照できます。スコープを設定すると、クラス、ファイル、またはコンテキストに可視性を限定でき、名前空間の汚染を減らし、見つけやすさを高められます。

ファイル限定の拡張関数

ファイルレベルで拡張関数に private を付けると、そのファイル内だけで使用できるようになります。

private fun String.shout() = uppercase() + "!"
fun main() {
    println("hello".shout()) // HELLO!
}

internal による可視性

internal を使用すると、拡張関数を現在のモジュール内に限定できます。外部での使用を想定しないライブラリ内部の処理に適しています。

internal fun List<Int>.sumIfPositive(): Int = filter { it > 0 }.sum()
fun main() {
    println(listOf(-1, 2, 3, -4).sumIfPositive()) // 5
}

メンバー拡張関数

拡張関数をクラスの内部で宣言すると、そのクラスのインスタンスがスコープ内にある場合にのみ使用できます。ディスパッチレシーバー(クラス)と拡張レシーバー(対象)の2つのレシーバーを持ちます。

class StringHelper(val prefix: String) {
    fun String.withPrefix() = prefix + this
    fun build(): String = "world".withPrefix() // calls extension via instance
}
fun main() {
    println(StringHelper("hello ").build()) // hello world
}

メンバー拡張関数の可視性

メンバー拡張関数には、ディスパッチクラスの外部からアクセスできません。カプセル化に役立ちます。

class Repo {
    fun List<Int>.allPositive() = all { it > 0 }
    fun check(xs: List<Int>) = xs.allPositive()
}
fun main() {
    val r = Repo()
    println(r.check(listOf(1, 2, 3))) // true
    // listOf(1).allPositive() // ERROR — no access
}

Companion Object の拡張

クラスの companion object に拡張関数を追加します。呼び出し側からは static メソッドのように見えますが、実際にはクラスの外部に存在します。

class Greeter {
    companion object
}
fun Greeter.Companion.morning() = "Good morning!"
fun main() {
    println(Greeter.morning())
}

Companion Object を拡張する理由

元のクラスを変更せずに、クラスの外部からファクトリーメソッドやヘルパーを追加する場合に便利です。

class User(val name: String) {
    companion object
}
fun User.Companion.guest() = User("Guest")
fun User.Companion.system() = User("System")
fun main() {
    println(User.guest().name)
    println(User.system().name)
}

空の Companion Object も必要

Companion Object の拡張を追加するには、クラスが companion object を(空であっても)宣言する必要があります。そうしないと、拡張先が存在しません。

class Box {
    companion object // required, even if empty
}
fun Box.Companion.create(): Box = Box()
fun main() {
    println(Box.create())
}

インポートによるスコープ付き拡張

特定のファイルでのみ拡張関数をインポートすることで、その使用範囲を限定できます。インポートしていないファイルからは見えません。

// File A:
// fun String.shout() = uppercase()
// File B imports:
// import com.example.shout
// Only File B can call shout()
fun String.shout() = uppercase() + "!"
fun main() { println("hi".shout()) }

スコープ関数による拡張関数の利用

with または apply を使用すると、拡張関数を使うためにオブジェクトを一時的にスコープへ追加できます。

class StringTools {
    fun String.greet() = "Hello, $this!"
    fun process(name: String) = with(this) {
        name.greet()
    }
}
fun main() {
    println(StringTools().process("Ada"))
}

コンパニオンの拡張プロパティ

コンパニオン拡張はプロパティにもできます。クラスの外部から名前付き定数を追加できます。

class HttpStatus {
    companion object
}
val HttpStatus.Companion.OK_CODE: Int get() = 200
val HttpStatus.Companion.NOT_FOUND: Int get() = 404
fun main() {
    println(HttpStatus.OK_CODE)
    println(HttpStatus.NOT_FOUND)
}

ベストプラクティス

ファイル内限定のヘルパーには private、モジュール内限定の API には internal、カプセル化にはメンバー拡張、外部からファクトリーのようなヘルパーを追加するにはコンパニオン拡張を使用してください。

class StringUtils {
    companion object
}
fun StringUtils.Companion.isAlpha(s: String) = s.all { it.isLetter() }
fun main() {
    println(StringUtils.isAlpha("hello"))
    println(StringUtils.isAlpha("hi5"))
}

クイックチェック

クラスの外部からそのクラスにコンパニオン拡張を追加するには、クラスに何が必要ですか?

まとめ

private、internal、またはクラス内のメンバー拡張として、拡張のスコープを限定してください。クラスで宣言されたコンパニオンオブジェクトに追加することで、外部からコンパニオン拡張(関数またはプロパティ)を追加できます。名前空間の汚染を抑えながら、コードをモジュール化できます。

無料で開始

AI チューターと学ぶ Kotlin — 無料

ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。

コース
51
レッスン
203

よくある質問

「スコープ付き拡張とcompanion拡張」レッスンは無料ですか?

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

「スコープ付き拡張とcompanion拡張」で何を学びますか?

拡張の可視性を制限し、companion objectに拡張を追加します。 ブラウザで直接実行するハンズオンコードでKotlin Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

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

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

「スコープ付き拡張とcompanion拡張」レッスンにはどのくらい時間がかかりますか?

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

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

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

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

  1. 拡張関数:構文とディスパッチ規則
  2. 拡張プロパティと計算拡張
  3. スコープ付き拡張とcompanion拡張
  4. 実践的な拡張:Context、View、Stringヘルパー
← Kotlin Academyに戻る