【Kotlin】レッスン5-08:メソッドのオーバーライドを理解しよう

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

この記事で学べる知識:メソッドのオーバーライド

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

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

Kotlinの「メソッドのオーバーライド」とは

この章ではKotlinにおける「メソッドのオーバーライド」の意味や使い方を学習します。用語の解説が不要な方はここをクリックして練習問題へ飛びましょう。




Kotlinにおいて「メソッドのオーバーライド」は、親クラスで定義されたメソッドを子クラスで再定義し、新たな挙動を与える機能です。

オブジェクト指向の特性を活かし、柔軟で再利用可能なコード設計に役立ちます。

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

メソッドのオーバーライドとは?

メソッドのオーバーライドとは、親クラスに定義されたメソッドを子クラスで同じ名前・引数を持つメソッドとして再定義することです。

これにより子クラスで特定の処理を上書きし、クラスの振る舞いを変更できます。

オーバーライドを使用するには、親クラスの関数がopen修飾子を持ち、子クラスではoverrideキーワードを使用する必要があります。

メソッドのオーバーライドの基本構文

Kotlinで関数をオーバーライドする基本構文は以下の通りです。

open class Parent {     // 親クラスとして使用されるParentクラスの定義
    open fun greet() {  // オーバーライドされることを想定したgreetメソッド
        println("Hello from Parent")
    }
}

class Child : Parent() {   // Parentクラスを継承したChildクラスの定義
    override fun greet() { // Parentクラスのgreetメソッドをオーバーライド
        println("Hello from Child")
    }
}
  • 親クラスParentのメソッドgreetopenキーワードを使用して再定義可能にしています。
  • 子クラスChildではoverrideキーワードを使用して新しい実装を提供しています。

メソッドのオーバーライドの使用例

メソッドのオーバーライドを活用した具体的なコード例を示します。

open class Animal {        // 親クラスとして使用するAnimalクラスの定義
    open fun makeSound() { // オーバーライドされることを想定したmakeSoundメソッドを定義
        println("Some generic animal sound")
    }
}

class Dog : Animal() {         // Animalクラスを継承したDogクラスを定義
    override fun makeSound() { // AnimalクラスのmakeSoundメソッドをオーバーライド
        println("Bark!")
    }
}

class Cat : Animal() {         // Animalクラスを継承したCatクラスを定義
    override fun makeSound() { // AnimalクラスのmakeSoundメソッドをオーバーライド
        println("Meow!")
    }
}

fun main() {
    val animals: List<Animal> = listOf(Dog(), Cat(), Animal())
    for (animal in animals) {
        animal.makeSound() // 各クラスに応じたサウンドが出力される
    }
}
  • 親クラスAnimalは汎用的な動物の行動を定義します。
  • 子クラスDogCatはそれぞれ特定の動物の挙動をmakeSound関数で再定義しています。
  • forループではリスト内の各インスタンスに応じて異なるメッセージが出力されます。

このコードを実行すると以下のように出力されます。

Bark!
Meow!
Some generic animal sound

オーバーライドの注意点

  1. openキーワード: 親クラスのメソッドはデフォルトでオーバーライドが禁止されています。オーバーライド可能にするにはopen修飾子を付ける必要があります。
  2. overrideキーワード: 子クラスでメソッドをオーバーライドする際は、必ずoverrideキーワードを使用します。これにより誤った再定義を防ぎます。
  3. アクセス修飾子: 親クラスと子クラス間で関数の可視性に互換性が必要です。例えば、protected関数をpublicに変更することは可能ですが、privateにすることはできません。

まとめ

Kotlinのメソッドのオーバーライドは、コードの柔軟性と再利用性を高める強力な機能です。

オーバーライドを正しく活用することで、親クラスの汎用性と子クラスの特化性を両立させ、オブジェクト指向プログラミングの真価を発揮できます。

メソッドのオーバーライドの練習問題

乗り物の動きを表現するプログラムを作成し、Kotlinの「メソッドのオーバーライド」を学びましょう。

基本となる「乗り物」のクラスを作成し、それを継承して「車」「船」「飛行機」の動きをそれぞれ異なる方法で実装します。

最後にこれらの乗り物の動きを表示するプログラムを作成してください。

この問題の要件

以下の要件に従ってコードを完成させてください。

  1. クラス Vehicle を作成すること。
    • move() という関数を定義し、「乗り物が移動します」と出力すること。
  2. クラス Car を作成し、Vehicle クラスを継承すること。
    • move() 関数をオーバーライドし、「車が道路を走ります」と出力すること。
  3. クラス Boat を作成し、Vehicle クラスを継承すること。
    • move() 関数をオーバーライドし、「船が水上を進みます」と出力すること。
  4. クラス Airplane を作成し、Vehicle クラスを継承すること。
    • move() 関数をオーバーライドし、「飛行機が空を飛びます」と出力すること。
  5. main関数 を作成すること。
    • Vehicle 型のリストを作成し、CarBoatAirplane のインスタンスをリストに追加すること。
    • すべてのインスタンスで move() 関数を呼び出し、動作を表示すること。

ただし、以下のような実行結果となるコードを書くこと。

*****↓↓正解コードの実行結果の例↓↓*****

車が道路を走ります
船が水上を進みます
飛行機が空を飛びます

この問題を解くヒント

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

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

正解のコードは上から順に以下のような構成となっています。
(※下記の□はコード内のインデントを表しています)

1:Vehicleクラスの定義
  □ moveメソッドの定義(open修飾子付き)
2:Carクラスの定義(Vehicleクラスを継承)
  □ moveメソッドをオーバーライド
3:Boatクラスの定義(Vehicleクラスを継承)
  □ moveメソッドをオーバーライド
4:Airplaneクラスの定義(Vehicleクラスを継承)
  □ moveメソッドをオーバーライド
5:main関数の定義
  □ Vehicle型のリストを作成し、Car、Boat、Airplaneのインスタンスを格納
  □ forループによりリストの各要素について処理
  □ □ moveメソッドを呼び出す

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

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

// 基本的な乗り物のクラス
open class Vehicle {
    /*【穴埋め問題1】
    ここにmoveメソッドを定義し、「乗り物が移動します」と出力するコードを書いてください。
    */
}

// 車クラス(Vehicleクラスを継承)
class Car : Vehicle() {
    /*【穴埋め問題2】
    ここにmoveメソッドをオーバーライドし、「車が道路を走ります」と出力するコードを書いてください。
    */
}

// 船クラス(Vehicleクラスを継承)
class Boat : Vehicle() {
    /*【穴埋め問題3】
    ここにmoveメソッドをオーバーライドし、「船が水上を進みます」と出力するコードを書いてください。
    */
}

// 飛行機クラス(Vehicleクラスを継承)
class Airplane : Vehicle() {
    /*【穴埋め問題4】
    ここにmoveメソッドをオーバーライドし、「飛行機が空を飛びます」と出力するコードを書いてください。
    */
}

fun main() {
    // Vehicle型のリストを作成
    val vehicles: List<Vehicle> = listOf(Car(), Boat(), Airplane())

    // 各乗り物に応じた動作を表示
    for (vehicle in vehicles) {
        // 【穴埋め問題5】ここでvehicleオブジェクトのmoveメソッドを呼び出してください。
    }
}

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

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



練習問題の解答と解説

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

正解コードの例

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

// 基本的な乗り物のクラス
open class Vehicle {
    // 乗り物の走行方法を表す関数
    open fun move() {
        println("乗り物が移動します")
    }
}

// 車クラス(Vehicleクラスを継承)
class Car : Vehicle() {
    // moveメソッドをオーバーライドして車特有の動作を実装
    override fun move() {
        println("車が道路を走ります")
    }
}

// 船クラス(Vehicleクラスを継承)
class Boat : Vehicle() {
    // moveメソッドをオーバーライドして船特有の動作を実装
    override fun move() {
        println("船が水上を進みます")
    }
}

// 飛行機クラス(Vehicleクラスを継承)
class Airplane : Vehicle() {
    // moveメソッドをオーバーライドして飛行機特有の動作を実装
    override fun move() {
        println("飛行機が空を飛びます")
    }
}

fun main() {
    // Vehicle型のリストを作成
    val vehicles: List<Vehicle> = listOf(Car(), Boat(), Airplane())

    // 各乗り物に応じた動作を表示
    for (vehicle in vehicles) {
        // オーバーライドされたメソッドが呼び出されることを確認
        vehicle.move()
    }
}

正解コードの解説

このプログラムではKotlinで「メソッドのオーバーライド」を学ぶことを目的としています。

プログラム全体をブロックごとに分け、使用されている文法を初心者にもわかりやすく解説します。

クラス Vehicle の定義

open class Vehicle {
    open fun move() {
        println("乗り物が移動します")
    }
}
  • open 修飾子: Kotlinではクラスやメソッドを継承可能にするには open を付ける必要があります。Vehicle クラスは他のクラスに継承されるためopen を指定しています。
  • move メソッド: 基本的な乗り物の動きを表現しています。このメソッドはオーバーライドされるためopen を付けています。

Car, Boat, Airplane クラスの定義と move メソッドのオーバーライド

class Car : Vehicle() {
    override fun move() {
        println("車が道路を走ります")
    }
}

class Boat : Vehicle() {
    override fun move() {
        println("船が水上を進みます")
    }
}

class Airplane : Vehicle() {
    override fun move() {
        println("飛行機が空を飛びます")
    }
}
  • class Car : Vehicle(): クラス CarVehicle を継承しています。: を使用して親クラスを指定します。
  • override 修飾子: 親クラスのメソッドを再定義する際に使います。このコードではそれぞれの乗り物に特有の動きを表現するため、move メソッドをオーバーライドしています。

main 関数でリストを使用して動作を表示

fun main() {
    val vehicles: List<Vehicle> = listOf(Car(), Boat(), Airplane())

    for (vehicle in vehicles) {
        vehicle.move()
    }
}
  • List: Kotlinのコレクション型の一つで複数の要素を保持できます。この場合、Vehicle 型のリストを作成しています。
  • listOf(Car(), Boat(), Airplane()): CarBoatAirplane のインスタンスをリストに追加します。
  • for: リストの各要素に対して繰り返し処理を行います。vehicle.move() によって、それぞれのオーバーライドされた move メソッドが呼び出されます。

まとめ

このプログラムではKotlinの「継承」と「メソッドのオーバーライド」の基礎を学びました。

実際にコードを動かしながら学ぶことで、理解が深まるでしょう!

次のステップとして自分で新しい乗り物を追加して、さらに異なる動きをプログラムに実装してみてください。

これによってオーバーライドの応用力が高まります。

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

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

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

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






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