【Python】レッスン5-05:クラスの継承を理解しよう

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

この記事で学べる知識:クラスの継承

この記事の練習問題で使用する知識:
レッスン1~4の知識クラスの定義と使用__init__メソッドメソッドの定義と使用カプセル化プロパティクラスの継承メソッドのオーバーライド静的メソッド、モジュール、抽象クラス、ミックスイン、データクラス

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

Pythonの「クラスの継承」とは

この章ではPythonにおける「クラスの継承」の意味や使い方を学習します。必要ない方はここをクリックして練習問題へ飛びましょう。



クラスの継承はオブジェクト指向プログラミングにおける重要な概念です。

既存のクラス(親クラス)の機能やプロパティを引き継いで、新しいクラス(子クラス)を作成します。これによりコードの再利用が促進され、重複したコードを書く必要がなくなります。

特に、複雑なシステムでは、継承を活用することでメンテナンス性が向上し、開発効率が高まります。

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

クラスの継承とは?

継承を使うことで、親クラスに定義されたメソッドや属性を子クラスが引き継ぎます。

子クラスは、親クラスのすべての機能をそのまま利用できるだけでなく、必要に応じて独自のメソッドや属性を追加したり、親クラスのメソッドを変更することも可能です。

これにより、新しい機能を柔軟に追加しながらも、既存のコードを最大限に活用することができます。

クラスの継承の使用例

以下はクラスの継承を実際に使った例です。

この例ではAnimalという親クラスを定義し、そのクラスを継承する子クラスDogを作成しています。

# 親クラス
class Animal:
    def __init__(self, name):
        self.name = name

    def speak(self):
        print(f"{self.name}が音を立てています")

# 子クラス
class Dog(Animal):
    def speak(self):
        print(f"{self.name}が吠えています")

# インスタンスの作成
dog = Dog("ポチ")
dog.speak()  # 出力: ポチが吠えています

このコードではAnimalクラスが基本的な属性nameとメソッドspeakを持っています。

DogクラスはAnimalクラスを継承し、親クラスの__init__メソッドを利用してname属性を初期化しますが、speakメソッドを独自に定義し直しています。

このように継承を使うことで親クラスの機能を再利用しつつ、子クラスに固有の振る舞いを追加することができます。

クラスの継承のメリット

クラスの継承を使う主なメリットは次の通りです。

  1. コードの再利用
    親クラスに一度定義したメソッドや属性は、子クラスで再利用できるため、重複コードを減らすことができます。
  2. 保守性の向上
    親クラスのコードを修正すると、その変更がすべての子クラスにも自動的に反映されるため、メンテナンスが容易になります。
  3. 拡張性の確保
    子クラスで独自の機能を追加することができるため、新しい機能を柔軟に追加できます。

これらの特徴を活用することで、効率的なプログラム設計が可能となります。

まとめ

クラスの継承は親クラスから子クラスへ機能を引き継ぐことにより、コードの再利用と保守性を向上させる手法です。

初心者にとっては最初少し難しく感じるかもしれませんが、実際にコードを書いてみるとその便利さが理解できるでしょう。

特に大規模なプロジェクトでは継承の力を借りて、シンプルかつ効率的なコード構造を実現できます。

練習問題5-5:車両クラスでオブジェクト指向を学ぼう

クラス継承を使った車両管理プログラムを作成しましょう。

親クラス「Vehicle」を定義し、その子クラスとして「Car」と「Motorcycle」を作成します。

各クラスは共通のメソッドを持ちつつ、固有の動作を追加します。プログラムでは車両の名前を設定し、対応する動作を実行するようにしてください。

この問題の要件

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

  • 親クラス「Vehicle」を定義し、名前を設定するコンストラクタと名前を表示するメソッドを作成すること。
  • 子クラス「Car」を「Vehicle」から継承し、車が走るメソッドを追加すること。
  • 子クラス「Motorcycle」を「Vehicle」から継承し、バイクが走るメソッドを追加すること。
  • 「Car」と「Motorcycle」クラスのオブジェクトを生成し、それぞれの動作を実行すること。

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

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

この乗り物はトヨタです。
この乗り物はハーレーです。
トヨタが道路を走っています。
ハーレーが高速道路を疾走しています。

この問題を解くヒント

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

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

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

1:親クラスVehicleの定義
  □ __init__メソッドで車両の名前を設定
  □ □ self.nameにnameを代入
2:introduceメソッドの定義
  □ 車両の名前を表示
3:子クラスCarの定義、Vehicleクラスを継承
  □ driveメソッドで車が道路を走る動作を定義
  □ □ printで「道路を走っています」を表示
4:子クラスMotorcycleの定義、Vehicleクラスを継承
  □ rideメソッドでバイクが高速道路を疾走する動作を定義
  □ □ printで「高速道路を疾走しています」を表示
5:Carクラスのインスタンス生成、トヨタを設定
6:Motorcycleクラスのインスタンス生成、ハーレーを設定
7:Carクラスのintroduceメソッドを呼び出し
8:Motorcycleクラスのintroduceメソッドを呼び出し
9:Carクラスのdriveメソッドを呼び出し
10:Motorcycleクラスのrideメソッドを呼び出し

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

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

# 親クラス(Vehicle)の定義
class Vehicle:
    # コンストラクタで車両の名前を設定
    """【穴埋め問題1】
    ここにコンストラクタを定義し、nameという引数を受け取り、self.nameにその値を設定するコードを書いてください。
    """

    # 親クラスのメソッド: 車両の名前を表示
    def introduce(self):
        print(f"この乗り物は{self.name}です。")

# 子クラス(Car)の定義、Vehicleクラスを継承
"""【穴埋め問題2】
ここにCarクラスを定義し、Vehicleクラスを継承してください。また、Carクラスに固有のdriveメソッドを定義し、{self.name}が道路を走っています。と表示するコードを書いてください。
"""

# 子クラス(Motorcycle)の定義、Vehicleクラスを継承
class Motorcycle(Vehicle):
    # Motorcycleクラス固有のメソッド: バイクが走る動作
    def ride(self):
        print(f"{self.name}が高速道路を疾走しています。")

# オブジェクトの生成
"""【穴埋め問題3】
ここにCarクラスのオブジェクトを生成し、"トヨタ"という名前を渡してください。また、Motorcycleクラスのオブジェクトを生成し、"ハーレー"という名前を渡してください。
"""

# 親クラスのメソッドを使って名前を表示
car.introduce()
motorcycle.introduce()

# CarクラスとMotorcycleクラスそれぞれの固有メソッドを使用
car.drive()
motorcycle.ride()

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

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



解答例と解説

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

正解コードの例

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

# 親クラス(Vehicle)の定義
class Vehicle:
    # コンストラクタで車両の名前を設定
    def __init__(self, name):
        self.name = name

    # 親クラスのメソッド: 車両の名前を表示
    def introduce(self):
        print(f"この乗り物は{self.name}です。")

# 子クラス(Car)の定義、Vehicleクラスを継承
class Car(Vehicle):
    # Carクラス固有のメソッド: 車が走る動作
    def drive(self):
        print(f"{self.name}が道路を走っています。")

# 子クラス(Motorcycle)の定義、Vehicleクラスを継承
class Motorcycle(Vehicle):
    # Motorcycleクラス固有のメソッド: バイクが走る動作
    def ride(self):
        print(f"{self.name}が高速道路を疾走しています。")

# オブジェクトの生成
car = Car("トヨタ")
motorcycle = Motorcycle("ハーレー")

# 親クラスのメソッドを使って名前を表示
car.introduce()  # ここではCarクラスがVehicleクラスからintroduceメソッドを継承している
motorcycle.introduce()  # Motorcycleクラスも同様に継承している

# CarクラスとMotorcycleクラスそれぞれの固有メソッドを使用
car.drive()  # Carクラスの固有メソッド
motorcycle.ride()  # Motorcycleクラスの固有メソッド

正解コードの解説

このコードでは「クラスの継承」について学べます。

クラスを使うことで同じような機能を持つ複数のオブジェクト(ここでは「Car」や「Motorcycle」)を効率的に扱えるようになります。

以下にブロックごとに解説していきます。

親クラス(Vehicle)の定義

class Vehicle:
    def __init__(self, name):
        self.name = name

    def introduce(self):
        print(f"この乗り物は{self.name}です。")

Vehicleクラスは、このコードの親クラスです。

このクラスではコンストラクタ(__init__)で名前を設定し、その名前を表示するメソッド(introduce)が定義されています。

親クラスは共通する機能を持たせるために作られ、他のクラスで使い回すことができるようにします。

  • __init__(self, name):オブジェクトが作られたときに名前を設定する初期化メソッドです。
  • introduce(self):車両の名前を表示するためのメソッドです。

子クラス(Car)の定義と継承

class Car(Vehicle):
    def drive(self):
        print(f"{self.name}が道路を走っています。")

Carクラスは親クラスであるVehicleを「継承」しています。

Pythonではクラスの後ろに(親クラス名)と書くことで、その親クラスの機能を子クラスで利用できるようにします。

この場合CarクラスはVehicleクラスのintroduceメソッドをそのまま使えるだけでなく、自分自身の新しいメソッド(drive)も持っています。

  • class Car(Vehicle)Vehicleクラスを継承し、新たに車専用の動作を追加しています。
  • drive(self):車が走る動作を表示するメソッドです。

子クラス(Motorcycle)の定義と継承

class Motorcycle(Vehicle):
    def ride(self):
        print(f"{self.name}が高速道路を疾走しています。")

Motorcycleクラスも同じくVehicleクラスを継承しています。

このクラスではintroduceメソッドを利用しつつ、新たにバイク特有の動作を表すrideメソッドを追加しています。

これによりコードの再利用性が高まり、Vehicleクラスに書いた機能を繰り返し書く必要がなくなります。

  • class Motorcycle(Vehicle):同様に親クラスのVehicleを継承し、新たにバイクの動作を定義しています。
  • ride(self):バイクが高速道路を走る動作を表すメソッドです。

オブジェクトの生成とメソッドの使用

car = Car("トヨタ")
motorcycle = Motorcycle("ハーレー")

car.introduce()
motorcycle.introduce()

car.drive()
motorcycle.ride()

ここではCarクラスとMotorcycleクラスのオブジェクトを作成しています。

作成されたオブジェクトはそれぞれのクラスの機能を持っており、親クラスから継承したintroduceメソッドを使用しています。

さらにCarクラスではdriveメソッド、Motorcycleクラスではrideメソッドを使って、それぞれ固有の動作を行います。

  • car = Car("トヨタ")Carクラスのオブジェクトを作成し、「トヨタ」という名前を設定します。
  • motorcycle = Motorcycle("ハーレー")Motorcycleクラスのオブジェクトを作成し、「ハーレー」という名前を設定します。
  • car.introduce()motorcycle.introduce():両方のオブジェクトで親クラスのintroduceメソッドを使用して名前を表示します。
  • car.drive()motorcycle.ride():それぞれのクラスで固有の動作を実行します。

まとめ

今回のコードでは「クラスの継承」を使って親クラス(Vehicle)から共通する機能を子クラス(CarMotorcycle)に引き継ぎました。

継承によって重複したコードを書く必要がなくなり、プログラムがより効率的に書けるようになります。

これを応用すればもっと複雑なプログラムでも柔軟に対応できるようになります。ぜひ、他の例も試して、理解を深めてください!

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

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

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

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






    Python記事トップへ戻る
    トップページへ戻る