【Kotlin】レッスン5-09:クラスの拡張を理解しよう

記事内に商品プロモーションを含む場合があります

この記事で学べる知識:クラスの拡張

この記事の練習問題を解くために必要な知識:
基礎文法、制御構造、関数、コレクション(レッスン1~4)クラスの定義と使用プライマリコンストラクタセカンダリコンストラクタアクセス修飾子とカプセル化クラスメンバとインスタンスメンバクラスの継承メソッドのオーバーライドクラスの拡張抽象クラスインターフェースデータクラス

<<前のページ Kotlin記事一覧 次のページ>>

Kotlinの文法「クラスの拡張」とは

ここではクラスの拡張の意味や使い方を学習します。必要ない方はここをクリックして練習問題へ飛びましょう。



Kotlin の「クラスの拡張」とは、既存のクラスやユーザーが定義したクラスに対して、新しいプロパティや関数を追加できる機能です。

この機能を使えばクラスのコードを変更することなく、独自の機能を簡単に追加できます。

初心者の方でも使いやすいこの機能は、標準クラス (StringInt など) や自分で作成したクラスを効率的に操作する際に非常に役立ちます。

本記事では「拡張プロパティ」と「拡張関数」の基本から具体例までを解説します。

【初心者向け】Kotlinのオブジェクト指向を分かりやすくまとめた概念図。 特にクラスの継承、オーバーライド、抽象クラス、インターフェース、データクラスの関係性を視覚的に理解できるようまとめている。

クラスの拡張とは?

Kotlin では、これまで使用してきたString 型や Int 型といったデータ型も、実はクラスの一種として実装されています。

つまり、文字列や数値を扱う機能がクラス内のメソッドやプロパティとして提供されています。

例えば、String クラスには文字列の長さを取得する length プロパティや、文字列をすべて大文字に変換する toUpperCase() 関数などがあります。

しかしこうした既存のクラス(例えばString)に新しい機能(例えばlengthやtoUpperCase)を加えたい場合、コードを書き換えることはできません。

そこで役立つのが「クラスの拡張」です。拡張を利用すれば、既存クラスにカスタムのプロパティや関数を追加できます。

なお拡張プロパティや拡張関数は トップレベルで定義することが一般的 です。

すなわちメイン関数の外で直接定義することで、コード全体で使えるようになります。

拡張プロパティとは?

拡張プロパティとは既存のクラスに新しいプロパティを追加する仕組みです。

たとえばString 型に「文字列の最初の文字を取得するプロパティ」を追加する例を見ていきましょう。

以下のコードでは String クラスにfirstCharという名前を付けた拡張プロパティを追加しています。

val String.firstChar: Char // Stringクラスを拡張してfirstCharという名のプロパティを追加
    get() = this[0]        // firstCharプロパティの処理内容

fun main() {                // メイン関数
    val text = "Kotlin"
    println(text.firstChar) // 定数textにfirstCharプロパティをあてて出力: K
}
  1. val String.firstChar: CharString クラスに firstChar という名前のプロパティを追加しています。
  2. get() = this[0]firstChar プロパティは、文字列の最初の文字(this[0])を返します。
  3. println(text.firstChar)text"Kotlin")の最初の文字を取得し、出力しています。

このように拡張プロパティを使えば、コードを簡潔にしつつ既存のクラスを拡張できます。

以下はユーザーが定義した User クラスに拡張プロパティを追加する例です。

class User(val name: String)

val User.initial: Char // Userクラスを拡張してinitialプロパティを追加
    get() = name[0]    // initialプロパティの処理内容

fun main() {
    val user = User("Alice")
    println(user.initial) // 定数userにinitialプロパティをあてて出力: A
}

この例ではUser クラスに initial プロパティを追加しています。これにより名前の最初の文字を取得できるようになります。

拡張関数とは?

拡張関数は既存のクラスに新しいメソッドを追加する仕組みです。

たとえばString 型に文字列の前に特定の文字列を付ける関数を追加することができます。

以下は String クラスに拡張関数を追加する例です。

// Stringクラスを拡張して、拡張関数addPrefixを定義
fun String.addPrefix(prefix: String): String {
    return "$prefix$this" // 戻り値(引数prefixと元の文字列を連結して返す)
}

fun main() {
    val text = "Kotlin"
    println(text.addPrefix("Hello, ")) // 定数textにaddPrefixをあてて出力: Hello, Kotlin
}
  1. fun String.addPrefix(prefix: String): StringString クラスに addPrefix という名前の関数を追加しています。
  2. return "$prefix$this"prefix(引数で指定された文字列)と this(元の文字列)を結合して返します。
  3. println(text.addPrefix("Hello, "))text"Kotlin")の前に "Hello, " を追加し、出力しています。

拡張関数の応用例

以下はUser クラスに拡張関数を追加する例です。

fun User.greet(): String {
    return "Hello, ${this.name}!"
}

fun main() {
    val user = User("Alice")
    println(user.greet()) // 出力: Hello, Alice!
}

この例ではUser クラスに greet 関数を追加して、挨拶文を生成しています。

まとめ

Kotlin のクラス拡張は既存クラスやユーザー定義クラスに機能を追加する便利な方法です。

拡張プロパティや拡張関数は、コードを簡潔かつ直感的にするための強力なツールです。特に以下の点に注意してください:

  • トップレベルでの定義:クラスや関数の外で定義することで、広いスコープで利用可能になります。
  • 再利用性:拡張機能により、同じクラスを使う複数の箇所で同じ機能を効率的に再利用できます。
  • 注意点:既存クラスのプロパティやメソッドと名前が衝突しないように注意が必要です。

拡張の基本を理解したら、ぜひ自分で実装を試してみてください!

クラスの拡張の練習問題:自分だけの便利な文字列操作を作ってみよう

文字列クラスを拡張し、プロパティと関数を追加する練習をしましょう。

まず文字列内の単語数を数える拡張プロパティを定義し、次に文字列内の単語順を反転する拡張関数を作成します。

これらを使い、サンプルの文字列に適用してその結果を画面に表示してください。

この問題の要件

以下の要件に従ってプログラムを作成してください。

  1. 拡張プロパティ wordCount を作成し、文字列内の単語数を取得できるようにすること。
    • 空白で区切られた単語を数えること。
  2. 拡張関数 reverseWords を作成し、文字列内の単語順を逆に並べ替えること。
    • 単語間は空白で分割し、逆順にして結合すること。
  3. サンプル文字列として「Kotlin を 学ぶ のは 楽しい」を使用すること。
  4. 拡張プロパティ wordCount を使用して単語数を表示すること。
  5. 拡張関数 reverseWords を使用して単語を逆順に並べ替えた結果を表示すること。

ただし、以下のような実行結果となること。

----- ↓出力される結果の例↓ -----

「Kotlin を 学ぶ のは 楽しい」の単語数は: 5 個です。
「Kotlin を 学ぶ のは 楽しい」を単語順に反転すると: 楽しい のは 学ぶ を Kotlin

この問題を解くヒント

1からコードを組み立てることが難しい場合は、以下のヒントを開いて参考にしましょう。

ヒント1【コードの構成を見る】

正解のコードは上から順に以下のような構成となっています。

1:Stringクラスに拡張プロパティwordCountを定義
  □ getメソッドの定義
  □ □ 文字列を空白で分割し、空でない部分の数を返す
2:Stringクラスに拡張関数reverseWordsを定義
  □ 文字列を空白で分割し、順序を反転させて再結合した結果を返す
3:main関数の定義
  □ String型の変数sentenceに”「Kotlin を 学ぶ のは 楽しい」”を代入
  □ printlnを用いて、sentenceの単語数をwordCountプロパティで取得し出力
  □ printlnを用いて、sentenceの単語をreverseWords関数で反転して出力

ヒント2【穴埋め問題にする】

以下のコードをコピーし、コメントに従ってコードを完成させて下さい。

// 文字列クラスに拡張プロパティを追加
/*【穴埋め問題1】
ここに文字列クラスに拡張プロパティwordCountを追加するコードを書いてください。
このプロパティは文字列内の単語数をカウントします。
*/

// 文字列クラスに拡張関数を追加
/*【穴埋め問題2】
ここに文字列クラスに拡張関数reverseWordsを追加するコードを書いてください。
この関数は文字列内の単語を反転した結果を返します。
*/

fun main() {
    // サンプル文字列
    val sentence = "Kotlin を 学ぶ のは 楽しい"

    // 拡張プロパティの使用例
    /*【穴埋め問題3】
    ここにsentenceを使ってwordCountプロパティを呼び出し、その結果を出力するコードを書いてください。
    */

    // 拡張関数の使用例
    /*【穴埋め問題4】
    ここにsentenceを使ってreverseWords関数を呼び出し、その結果を出力するコードを書いてください。
    */
}

この問題の穴埋めコードは以上です。

このヒントを見てもまだ回答を導き出すのが難しいと感じる場合は、先に正解のコードと解説を見て内容を理解するようにしましょう。

練習問題の解答と解説

この問題の一つの正解例とそのコードの解説を以下に示します。

正解コードの例

例えば以下のようなプログラムが考えられます。

// 文字列クラスに拡張プロパティを追加
val String.wordCount: Int
    get() {
        // 文字列内の単語数をカウント(空白で分割して数える)
        return this.split(" ").filter { it.isNotEmpty() }.size
    }

// 文字列クラスに拡張関数を追加
fun String.reverseWords(): String {
    // 文字列内の単語を反転する
    return this.split(" ").reversed().joinToString(" ")
}

fun main() {
    // サンプル文字列
    val sentence = "Kotlin を 学ぶ のは 楽しい"

    // 拡張プロパティの使用例
    println("「$sentence」の単語数は: ${sentence.wordCount} 個です。")

    // 拡張関数の使用例
    println("「$sentence」を単語順に反転すると: ${sentence.reverseWords()}")
}

正解コードの解説

このKotlinコードではクラスの拡張機能を使用して、文字列クラスに新しいプロパティと関数を追加しています。

コードをブロックごとに分けて解説します。

拡張プロパティ wordCount

val String.wordCount: Int
    get() {
        return this.split(" ").filter { it.isNotEmpty() }.size
    }
  1. 拡張プロパティ:
    • 既存のクラス(この場合はString)に新しいプロパティを追加します。
    • wordCountは文字列内の単語数を数えます。
  2. このプロパティの仕組み:
    • split(" "): 空白で文字列を分割します。
    • filter { it.isNotEmpty() }: 空でない単語のみをフィルタします。
    • size: 単語の数を取得します。

: 文字列 "Kotlin を 学ぶ のは 楽しい" の単語数は5です。

拡張関数 reverseWords

fun String.reverseWords(): String {
    return this.split(" ").reversed().joinToString(" ")
}
  1. 拡張関数:
    • 既存のクラスに新しい関数を追加します。
    • reverseWordsは文字列内の単語順を反転します。
  2. この関数の仕組み:
    • split(" "): 空白で文字列を分割します。
    • reversed(): 単語のリストを逆順に並べ替えます。
    • joinToString(" "): 単語を空白で結合して新しい文字列を作ります。

: 文字列 "Kotlin を 学ぶ のは 楽しい" は反転すると "楽しい のは 学ぶ を Kotlin" になります。

メイン関数

fun main() {
    val sentence = "Kotlin を 学ぶ のは 楽しい"
    println("「$sentence」の単語数は: ${sentence.wordCount} 個です。")
    println("「$sentence」を単語順に反転すると: ${sentence.reverseWords()}")
}
  • 文字列sentenceを定義します。
  • 拡張プロパティwordCountを使用して単語数を表示します。
  • 拡張関数reverseWordsを使用して単語を反転した結果を表示します。

まとめ

今回のコードではKotlinの「クラスの拡張」を使って、既存のStringクラスに新しい機能を追加しました。

拡張プロパティと拡張関数を利用すると、既存のクラスを簡単にカスタマイズでき、コードの再利用性や可読性を高められます。

この機能をマスターすれば、独自のユーティリティ関数を作成してKotlinプログラムをより効率的に構築できるようになります。

ぜひ、自分のプロジェクトで試してみてください!

<<前のページ Kotlin記事一覧 次のページ>>

この記事への質問・コメント

この記事を作成するにあたりAIを活用しています。

問題ないことは確認していますが、もし間違いや表現の違和感などありましたら、ご指摘頂けると大変助かります。






    Kotlinテキスト&問題集へ戻る
    トップページへ戻る