Kotlin練習問題2-8:クラスの継承を理解しよう

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

Kotlinの初心者向け問題2-8:クラスの継承を理解しよう

この問題を解くために必要な知識:
【レベル1の知識】
コメントの書き方、変数と定数、基本データ型、算術演算と論理演算、入力と出力、import文、配列、分岐処理(if、if~else、when)、繰り返し処理(for、while、do~while)、Null安全、スマートキャスト

【レベル2の知識】
関数の定義と呼び出し、関数の戻り値関数のオーバーロードラベルとジャンプ例外処理、クラスの定義と使用、インスタンス、コンストラクタ、プロパティ、クラスの継承、クラスの拡張

<<前の問題 問題集Top 次の問題>>

Kotlinの文法「クラスの継承」とは

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



Kotlinでは、クラスの継承を使うことでコードの再利用や拡張が容易になります。

オブジェクト指向プログラミングの重要な概念である「継承」は、プログラムの保守性や拡張性を向上させるために非常に役立ちます。

今回は、その基本的な使い方について解説します。

クラスの継承とは?

クラスの継承は、既存のクラス(親クラス、スーパークラス)の機能を新しいクラス(子クラス、サブクラス)に引き継ぐための仕組みです。

これにより、新しいクラスは親クラスが持つメソッドやプロパティをそのまま使ったり、必要に応じて変更することができます。

Kotlinでは、クラスはデフォルトで継承できないように設計されています。

つまり、クラスを継承可能にするためには、親クラスにopen修飾子を付ける必要があります。

加えて、子クラスが親クラスのメソッドを変更(オーバーライド)する場合には、overrideキーワードを使用します。

クラス継承の使用例

次に、Kotlinでクラス継承を実際にどのように実装するか、具体的な例を見ていきましょう。

// 親クラス(スーパークラス)
open class Animal {
    open fun makeSound() {
        println("Animal makes a sound")
    }
}

// 子クラス(サブクラス)
class Dog : Animal() {
    override fun makeSound() {
        println("Dog barks")
    }
}

fun main() {
    val dog = Dog()
    dog.makeSound() // Dog barks
}

このコードでは、Animalクラスが親クラス(スーパークラス)として定義されています。

AnimalクラスにはmakeSound()というメソッドが定義されており、これを子クラスであるDogクラスが継承しています。

Dogクラスは親クラスのmakeSound()メソッドをoverrideキーワードで上書きし、犬特有の音(”Dog barks”)を出力するように変更しています。

Kotlinでの継承のポイント

Kotlinでクラスを継承する際には、いくつかのポイントを押さえておく必要があります。

  • open修飾子:クラスやメソッドを継承可能にするために使用します。openが付いていないクラスやメソッドは、デフォルトで継承やオーバーライドができません。
  • overrideキーワード:親クラスのメソッドを上書きする際に使います。このキーワードが無いと、メソッドのオーバーライドはできません。また、親クラスのメソッドにはopen修飾子が必要です。
  • 親クラスのコンストラクタ呼び出し:子クラスが親クラスを継承する際には、親クラスのコンストラクタも呼び出す必要があります。このため、親クラスに引数付きのコンストラクタがある場合、子クラスもその引数を渡してコンストラクタを呼び出す必要があります。

まとめ

Kotlinのクラス継承は、オブジェクト指向プログラミングの基本的な機能の一つであり、コードの再利用性を高めることができます。

クラスを継承することで、新しい機能を簡単に追加したり、既存の機能を変更できるため、保守性や拡張性の高いプログラムが作成可能です。

ただし、Kotlinではクラスやメソッドを明示的にopenにしない限り、継承が許されないため、必要な場所で適切にopenoverrideを使うことが重要です。




Kotlin練習問題2-8_犬と猫の情報を表示するプログラム

Kotlinの「クラスの継承」を理解するために、動物のクラスをベースに犬と猫のクラスを作成するプログラムを作りましょう。

このプログラムでは、動物の基本的な情報を管理するAnimalクラスを定義し、そのAnimalクラスを継承したDogクラスとCatクラスを作成します。

これにより、犬と猫の名前を表示し、それぞれの鳴き声をコンソールに表示するプログラムを完成させます。

この問題の要件

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

  • Animalという名前のクラスを作成し、nameという名前のプロパティを持たせること。このプロパティはコンストラクタを使用して初期化します。
  • Animalクラスに、動物の名前を表示するdisplayInfoという関数を作成すること。この関数では、nameプロパティの値を使用して、「動物の名前: [name]」という形でコンソールに出力します。
  • Animalクラスを継承したDogクラスを作成し、Dogクラスに犬の鳴き声を表示するbarkという関数を定義すること。この関数では、「[name] はワンワンと鳴いています。」とコンソールに出力します。
  • 同様に、Animalクラスを継承したCatクラスを作成し、Catクラスに猫の鳴き声を表示するmeowという関数を定義すること。この関数では、「[name] はニャーニャーと鳴いています。」とコンソールに出力します。
  • main関数を作成し、DogクラスとCatクラスのインスタンスを作成すること。それぞれに適切な名前を与え、displayInfo関数と鳴き声を表示する関数を呼び出して、結果をコンソールに出力すること。

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

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

動物の名前: ポチ
ポチ はワンワンと鳴いています。
動物の名前: タマ
タマ はニャーニャーと鳴いています。

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

この問題を解くヒント

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

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

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

1.Animalクラスの定義
 1-1. nameプロパティの宣言と初期化(コンストラクタ)
 1-2. displayInfo関数の定義(動物の名前を表示)

2.Dogクラスの定義
 2-1. Animalクラスからの継承
 2-2. bark関数の定義(犬の鳴き声を表示)

3.Catクラスの定義
 3-1. Animalクラスからの継承
 3-2. meow関数の定義(猫の鳴き声を表示)

4.main関数の定義
 4-1. Dogクラスのインスタンス化
 4-2. Catクラスのインスタンス化
 4-3. displayInfo関数を使用して名前を表示
 4-4. bark関数を使用して犬の鳴き声を表示
 4-5. displayInfo関数を使用して名前を表示
 4-6. meow関数を使用して猫の鳴き声を表示

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

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

// Animalクラスを定義
open class Animal(val name: String) {
    // 名前を表示する関数
    fun displayInfo() {
        /* 【穴埋め問題1】
        ここにnameプロパティを使用して、動物の名前を表示するコードを書いてください。
        例: println("動物の名前: $name")
        */
    }
}

// DogクラスをAnimalクラスから継承
class Dog(name: String) : Animal(name) {
    // 犬の鳴き声を表示する関数
    fun bark() {
        /* 【穴埋め問題2】
        ここにnameプロパティを使用して、犬の鳴き声を表示するコードを書いてください。
        例: println("$name はワンワンと鳴いています。")
        */
    }
}

// CatクラスをAnimalクラスから継承
class Cat(name: String) : Animal(name) {
    // 猫の鳴き声を表示する関数
    fun meow() {
        /* 【穴埋め問題3】
        ここにnameプロパティを使用して、猫の鳴き声を表示するコードを書いてください。
        例: println("$name はニャーニャーと鳴いています。")
        */
    }
}

fun main() {
    // Dogクラスのインスタンスを作成
    /* 【穴埋め問題4】
    ここにDogクラスのインスタンスを作成するコードを書いてください。
    例: val dog = Dog("ポチ")
    */
    
    // Catクラスのインスタンスを作成
    /* 【穴埋め問題5】
    ここにCatクラスのインスタンスを作成するコードを書いてください。
    例: val cat = Cat("タマ")
    */
    
    // 犬の名前を表示
    /* 【穴埋め問題6】
    ここにdogインスタンスのdisplayInfo関数を呼び出すコードを書いてください。
    例: dog.displayInfo()
    */

    // 犬の鳴き声を表示
    /* 【穴埋め問題7】
    ここにdogインスタンスのbark関数を呼び出すコードを書いてください。
    例: dog.bark()
    */
    
    // 猫の名前を表示
    /* 【穴埋め問題8】
    ここにcatインスタンスのdisplayInfo関数を呼び出すコードを書いてください。
    例: cat.displayInfo()
    */
    
    // 猫の鳴き声を表示
    /* 【穴埋め問題9】
    ここにcatインスタンスのmeow関数を呼び出すコードを書いてください。
    例: cat.meow()
    */
}

 

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

解答例

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

正解コードの例

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

********************

// Animalクラスを定義
open class Animal(val name: String) {
    // 名前を表示する関数
    fun displayInfo() {
        println("動物の名前: $name")
    }
}

// DogクラスをAnimalクラスから継承
// クラスの継承により、Animalクラスのプロパティとメソッドを引き継ぎます
class Dog(name: String) : Animal(name) {
    // 犬の鳴き声を表示する関数
    fun bark() {
        println("$name はワンワンと鳴いています。")
    }
}

// CatクラスをAnimalクラスから継承
// Dogクラスと同様に、Animalクラスのプロパティとメソッドを引き継いでいます
class Cat(name: String) : Animal(name) {
    // 猫の鳴き声を表示する関数
    fun meow() {
        println("$name はニャーニャーと鳴いています。")
    }
}

fun main() {
    // Dogクラスのインスタンスを作成
    // Animalクラスのプロパティnameは、Dogクラスのインスタンス作成時に初期化されます
    val dog = Dog("ポチ")
    // Catクラスのインスタンスを作成
    // 同様に、Animalクラスのプロパティnameが初期化されます
    val cat = Cat("タマ")

    // 犬の名前を表示
    // 継承したdisplayInfoメソッドを使用しています
    dog.displayInfo()
    // 犬の鳴き声を表示
    dog.bark()

    // 猫の名前を表示
    // 同様に、継承したdisplayInfoメソッドを使用しています
    cat.displayInfo()
    // 猫の鳴き声を表示
    cat.meow()
}

********************

コードの解説

このコードは、Kotlinで「クラスの継承」を使って、動物(Animal)クラスを基本にして犬(Dog)クラスと猫(Cat)クラスを作成する方法を学ぶためのものです。

それぞれのクラスや関数の役割について解説します。

Animalクラスの定義

open class Animal(val name: String) {
    fun displayInfo() {
        println("動物の名前: $name")
    }
}
  • open class Animal(val name: String): Animalクラスは動物を表すクラスです。nameという名前のプロパティを持ち、nameはインスタンス化されるときに初期化されます。openキーワードは、このクラスが他のクラスから継承されることを意味します。
  • fun displayInfo(): この関数は、動物の名前を表示します。println関数を使って、nameプロパティの値を出力します。

Dogクラスの定義

class Dog(name: String) : Animal(name) {
    fun bark() {
        println("$name はワンワンと鳴いています。")
    }
}
  • class Dog(name: String) : Animal(name): DogクラスはAnimalクラスを継承しています。つまり、Animalクラスのプロパティやメソッドをそのまま利用できます。nameプロパティはAnimalクラスから継承され、コンストラクタで初期化されます。
  • fun bark(): Dogクラスに特有の関数で、犬の鳴き声を出力します。nameプロパティを使用して、具体的な犬の名前と鳴き声を出力します。

Catクラスの定義

class Cat(name: String) : Animal(name) {
    fun meow() {
        println("$name はニャーニャーと鳴いています。")
    }
}
  • class Cat(name: String) : Animal(name): CatクラスもAnimalクラスを継承しています。これにより、Animalクラスのプロパティやメソッドを利用できます。
  • fun meow(): Catクラスに特有の関数で、猫の鳴き声を出力します。nameプロパティを使用して、猫の名前と鳴き声を出力します。

main関数の定義

fun main() {
    val dog = Dog("ポチ")
    val cat = Cat("タマ")
    
    dog.displayInfo()
    dog.bark()
    
    cat.displayInfo()
    cat.meow()
}
  • val dog = Dog("ポチ"): Dogクラスのインスタンスを作成し、ポチという名前を与えます。このとき、Animalクラスのnameプロパティがポチに初期化されます。
  • val cat = Cat("タマ"): Catクラスのインスタンスを作成し、タマという名前を与えます。このとき、Animalクラスのnameプロパティがタマに初期化されます。
  • dog.displayInfo()dog.bark(): Dogインスタンスであるdogの名前を表示し、続けて鳴き声を表示します。
  • cat.displayInfo()cat.meow(): Catインスタンスであるcatの名前を表示し、続けて鳴き声を表示します。
<<前の問題 問題集Top 次の問題>>

この問題への質問・コメント

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

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






    Kotlin練習問題集へ戻る
    トップページへ戻る