拡張プロパティとは、クラスへの拡張であり、状態(バックフィールド)を追加することなくゲッターとセッターを追加することを可能にします。Javaにはこの機能がないため、ユーティリティメソッドを作成することが類似の機能となります。歴史的に、機能を追加するためには静的メソッドやラッパーオブジェクトを使用する必要がありました。
問題: 外部クラスにはしばしば必要なプロパティが不足しています。カプセル化を破らずに簡潔で安全にクラスを拡張したいと思います。
解決策: Kotlinでは、通常のプロパティのように見える拡張プロパティを宣言できますが、それは関数の形で実装されています。これにより、元のソースコードにアクセスできない型を便利な方法で拡張できます。
コードの例:
val String.firstChar: Char get() = this[0] println("Kotlin".firstChar) // K
主な特徴:
拡張プロパティにバックフィールド(状態)を追加できますか?
いいえ、拡張プロパティは瞬時に値を計算するだけで、状態を保存することはできません。
拡張プロパティは継承クラスのプロパティをオーバーライドできますか?
いいえ、拡張プロパティ(および拡張関数)は本質的に静的です。オーバーライドや仮想にはできません。
拡張プロパティはどのようにコンパイルされ、通常のプロパティの構文的な類似物ではないのはなぜですか?
拡張プロパティは実際には静的なゲッター(および/またはセッター)関数にコンパイルされます。クラスのエンティティには含まれず、宣言されたファイルのコンテキストでのみ見えます。
ネガティブケース
開発者は、標準のAndroid Viewに対して「訪問済み」状態を保持するための拡張プロパティを追加しようとしました:
var View.isVisited: Boolean get() = ... set(value) { ... } // エラー: 保存場所がありません
利点:
欠点:
ポジティブケース
Stringの拡張プロパティが実装され、拡張されたフォーマットを取得します:
val String.asTitle: String get() = this.replaceFirstChar { it.uppercase() }
利点:
欠点: