[Pythonのはじめ方] Part22: 継承とオーバーライド

Python

オブジェクト指向プログラミングの強力な機能、「継承」と「オーバーライド」へようこそ!✨ これらをマスターすると、コードの再利用性が格段に上がり、より効率的で保守しやすいプログラムを書けるようになります。このステップで、その基本をしっかり学びましょう!

1. 継承 (Inheritance) とは? 🤔

継承とは、すでにあるクラス(親クラス または スーパークラス)の機能(属性やメソッド)を引き継いで、新しいクラス(子クラス または サブクラス)を作成する仕組みです。

例えるなら、乗り物という「親クラス」があり、その特徴(移動できる、定員があるなど)を引き継いで、自動車や自転車といった具体的な「子クラス」を作るようなイメージです。🚗🚲

継承のメリット:

  • コードの再利用: 親クラスのコードをそのまま使えるので、同じようなコードを何度も書く必要がなくなります。
  • 階層構造: クラス同士の関係性(is-a関係: 例「犬は動物である」)を明確に表現できます。
  • 保守性の向上: 親クラスの修正が、それを継承するすべての子クラスに反映されるため、修正箇所が少なくなります。

基本的な書き方

Pythonでクラスを継承するには、クラス定義の際に括弧 () の中に親クラス名を指定します。

# 親クラスの定義
class Animal:
    def __init__(self, name):
        self.name = name
        print(f"Animal {self.name} が生まれました。")

    def eat(self):
        print(f"{self.name} は食事をしています。")

# 子クラスの定義 (Animalクラスを継承)
class Dog(Animal): # 括弧の中に親クラス名を指定
    def bark(self):
        print(f"{self.name} はワン!と吠えています。")

# 子クラスのインスタンスを作成
my_dog = Dog("ポチ")

# 親クラスから継承したメソッドを使える
my_dog.eat()

# 子クラスで定義したメソッドも使える
my_dog.bark()

実行結果:

Animal ポチ が生まれました。
ポチ は食事をしています。
ポチ はワン!と吠えています。

Dog クラスは Animal クラスを継承しているので、Animal で定義された __init__ メソッドや eat メソッドをそのまま利用できます。

super() 関数: 親クラスのメソッドを呼び出す

子クラスで親クラスと同じ名前のメソッド(特に __init__)を定義した場合、親クラスのメソッドは自動では呼ばれなくなります。親クラスのメソッドを明示的に呼び出したい場合は super() 関数を使います。

class Animal:
    def __init__(self, name):
        print("Animalの __init__ が呼ばれました。")
        self.name = name

class Dog(Animal):
    def __init__(self, name, breed):
        print("Dogの __init__ が呼ばれました。")
        # super() を使って親クラス(Animal)の __init__ メソッドを呼び出す
        super().__init__(name)
        self.breed = breed # Dogクラス独自の属性を追加
        print(f"犬種は {self.breed} です。")

    def bark(self):
        print(f"{self.name} はワン!")

my_dog = Dog("ハチ", "秋田犬")
print(f"犬の名前: {my_dog.name}")

実行結果:

Dogの __init__ が呼ばれました。
Animalの __init__ が呼ばれました。
犬種は 秋田犬 です。
犬の名前: ハチ

Dog__init__ 内で super().__init__(name) を呼び出すことで、Animal__init__ が実行され、self.name 属性が設定されています。

2. オーバーライド (Override) とは? 덮어쓰기

オーバーライドとは、親クラスから継承したメソッドを、子クラスで再定義することです。これにより、子クラス独自の振る舞いをさせることができます。

例えば、Animal クラスに speak メソッド(鳴く)があっても、動物の種類によって鳴き声は違いますよね?🐶🐱 Dog クラスでは「ワン!」、Cat クラスでは「ニャー!」と鳴くように、speak メソッドをそれぞれのクラスでオーバーライドします。

オーバーライドのメリット:

  • クラスごとのカスタマイズ: 同じメソッド名でも、クラスによって異なる処理を実行させることができます(ポリモーフィズム(多態性)の実現)。
  • 柔軟性の向上: 基本的な動作は親クラスで定義し、具体的な動作は子クラスで調整できます。

基本的な書き方

オーバーライドは、子クラスで親クラスと同じ名前のメソッドを定義するだけです。

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

    def speak(self):
        # デフォルトの鳴き声 (子クラスでオーバーライドされることを期待)
        print(f"{self.name} は...と鳴いています。")

class Dog(Animal):
    # Animalクラスの speak メソッドをオーバーライド
    def speak(self):
        print(f"{self.name} はワン!と鳴いています。")

class Cat(Animal):
    # Animalクラスの speak メソッドをオーバーライド
    def speak(self):
        print(f"{self.name} はニャー!と鳴いています。")

my_dog = Dog("ポチ")
my_cat = Cat("タマ")

my_dog.speak() # Dogクラスでオーバーライドされた speak が呼ばれる
my_cat.speak() # Catクラスでオーバーライドされた speak が呼ばれる

# Animalクラスのインスタンスも作ってみる
generic_animal = Animal("動物")
generic_animal.speak()

実行結果:

ポチ はワン!と鳴いています。
タマ はニャー!と鳴いています。
動物 は...と鳴いています。

DogCat のインスタンスでは、それぞれのクラスでオーバーライド(再定義)された speak メソッドが実行されています。

3. 継承とオーバーライドの組み合わせ例 🛠️

継承とオーバーライドは組み合わせて使うことで、その真価を発揮します。親クラスの共通機能は継承しつつ、子クラス固有の振る舞いをオーバーライドで実現しましょう。

ここでは、super() を使って親クラスのメソッドを呼び出しつつ、子クラス独自の処理を追加する例を見てみましょう。

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

    def greet(self):
        print(f"こんにちは、私は {self.name} です。")

class Dog(Animal):
    def __init__(self, name, breed):
        super().__init__(name) # 親クラスの__init__を呼び出してnameを設定
        self.breed = breed

    # 親クラスの greet メソッドをオーバーライド
    def greet(self):
        super().greet() # 親クラスの greet メソッドをまず呼び出す
        # 子クラス独自の処理を追加
        print(f"私の犬種は {self.breed} です。よろしくね!🐾")

my_dog = Dog("レオ", "ゴールデンレトリバー")
my_dog.greet()

実行結果:

こんにちは、私は レオ です。
私の犬種は ゴールデンレトリバー です。よろしくね!🐾

Doggreet メソッドでは、まず super().greet() で親クラスの挨拶を実行し、その後で犬種に関する情報を追加しています。このように、親クラスの機能を活用しつつ拡張することができます。

4. まとめ 📝

今回は、オブジェクト指向プログラミングにおける重要な概念である「継承」と「オーバーライド」について学びました。

  • 継承: 親クラスの機能を引き継ぎ、コードの再利用性を高める。class Child(Parent):
  • オーバーライド: 親クラスから継承したメソッドを子クラスで再定義し、独自の振る舞いをさせる。
  • super(): 子クラスから親クラスのメソッドを呼び出す際に使用する。

これらの概念を理解し使いこなすことで、より洗練された、構造化されたPythonプログラムを作成できるようになります。繰り返し練習して、ぜひ身につけてくださいね!💪

次は、オブジェクト指向のもう一つの重要な柱である「カプセル化」や、クラス変数・インスタンス変数について学んでいきましょう!

参考情報

コメント

タイトルとURLをコピーしました