MENU

【Kotlin】レッスン5-09:クラスの拡張とは?拡張関数とプロパティを使いこなそう

tggaa478@yahoo.co.jp

一つ前のページではメソッドのオーバーライドについて学習しました。

今回は クラスを拡張 について見ていきましょう。

Lesson1:基礎文法編
Lesson2:制御構造編
Lesson3:関数編
Lesson4:コレクション編
Lesson5:オブジェクト指向編

 ・Lesson5-1:クラスの基本を理解しよう
 ・Lesson5-2:プライマリコンストラクタを理解しよう
 ・Lesson5-3:セカンダリコンストラクタを理解しよう
 ・Lesson5-4:ふたつのコンストラクタを使いこなそう
 ・Lesson5-5:アクセス修飾子とカプセル化を理解しよう
 ・Lesson5-6:クラスメンバとインスタンスメンバを理解しよう
 ・Lesson5-7:クラスの継承を理解しよう
 ・Lesson5-8:メソッドのオーバーライドを理解しよう
 ・Lesson5-9:クラスを拡張しよう ◁今回はココ
 ・Lesson5-10:抽象クラスを理解しよう
 ・Lesson5-11:インターフェースを理解しよう
 ・Lesson5-12:データクラスを理解しよう
 ・確認問題5-☆1:モンスター捕獲ゲームを作ろう
 ・確認問題5-☆2:マルバツゲームを作ろう
 ・確認問題5-☆3:石取りゲームを作ろう

<<前のページ

学習記事一覧

次のページ>>

Kotlinのクラス拡張機能とは?|拡張関数とプロパティの基礎を学ぼう

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

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

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

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

クラス拡張の仕組みと使い道を理解しよう

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からコードを組み立てることが難しい場合は、以下のヒントを開いて参考にしましょう。

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

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

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

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

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

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

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

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

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

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

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

練習問題の解答と解説

この問題の正解コードとその解説は以下の通りです。

クリックして開いて確認してください。

Q
正解コード
// 文字列クラスに拡張プロパティを追加
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()}")
}
Q
正解コードの解説

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

拡張プロパティ 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学習サイトにするため、ぜひ 問い合わせフォーム からご意見下さい。

<<前のページ

学習記事一覧

次のページ>>

記事URLをコピーしました