このページで解説している内容は、以下の YouTube 動画の解説で見ることができます。

【Python入門】クラスに新しいメソッドを追加する

クラスに新しいメソッドを追加する

 派生クラスでは、基底クラスから継承したメソッドをオーバーライドするだけでなく、基底クラスに存在しない新しいメソッドを追加 することもできます。こうしたメソッドは派生クラスのオブジェクトでのみ利用できるため、クラスごとに固有の機能を実装するのに適しています。ここでは、派生クラスへの新メソッドの追加について分かりやすく解説します。

プログラムのダウンロード

 「ダウンロード」から、JupyterLab で実行できるサンプルプログラムがダウンロードできます。ファイルは、ESET Endpoint Securityでウイルスチェックをしておりますが、ダウンロードとプログラムの実行は自己責任でお願いいたします。

1.新しいメソッドを追加する意義

1.1. 個別の機能を明確にできる

 基底クラスで共通機能をまとめつつ、派生クラスで特有の操作を実装する場合、基底クラスに含めるとかえって複雑になりがちな機能でも、派生クラスで新たなメソッドとして定義すればコードの見通しが良くなります。

1.2. クラス設計の柔軟性が高まる

 ある派生クラスでは追加のメソッドが必要でも、別の派生クラスでは不要というケースはよくあります。共通の土台を維持しつつ、派生クラスごとに独自のメソッドを追加することで、継承による再利用拡張性 のバランスを取りやすくなります。

2.サンプルコード:派生クラスにメソッドを追加する

 以下では、基底クラスとして「Deviceクラス」を用い、派生クラスとして「Cameraクラス」と「Printerクラス」を定義します。カメラには「シャッターを切る(撮影する)」機能を、プリンターには「印刷する」機能を新メソッドとして追加し、それぞれのオブジェクトで確認してみます。

# 基底クラス: Device
class Device:
    def __init__(self, name, price):
        self.name = name
        self.price = price

    def show(self):
        print("Name:", self.name)
        print("Price:", self.price)

# 派生クラス: Camera
class Camera(Device):
    def __init__(self, name, price, megapixels):
        super().__init__(name, price)
        self.megapixels = megapixels

    def show(self):
        # 基底クラスのshow()を呼び出して共通部分を表示
        super().show()
        print("Resolution (MP):", self.megapixels)

    def shoot(self):
        # Cameraクラス独自のメソッド
        print("Shooting a photo with", self.name)

# 派生クラス: Printer
class Printer(Device):
    def __init__(self, name, price, paper_size):
        super().__init__(name, price)
        self.paper_size = paper_size

    def show(self):
        # 基底クラスのshow()を呼び出して共通部分を表示
        super().show()
        print("Paper Size:", self.paper_size)

    def print_doc(self):
        # Printerクラス独自のメソッド
        print("Printing document on", self.name)

# Cameraオブジェクトの生成とメソッドの呼び出し
c = Camera("AlphaCam", 30000, 24)
c.show()
c.shoot()

print()

# Printerオブジェクトの生成とメソッドの呼び出し
p = Printer("ProPrinter", 15000, "A4")
p.show()
p.print_doc()

実行結果

Name: AlphaCam
Price: 30000
Resolution (MP): 24
Shooting a photo with AlphaCam

Name: ProPrinter
Price: 15000
Paper Size: A4
Printing document on ProPrinter

詳しい解説

  • Deviceクラス(基底クラス)
    __init__ メソッドで nameprice を共通のデータ属性として初期化
    show メソッドで、そのデータ属性を表示する。
  • Cameraクラス(派生クラス)
    Device から継承する形で、megapixels(画素数)を独自の属性として追加
    ・基底クラスの show を呼び出しつつ、追加の情報を出力するようオーバーライド
    shoot メソッドは Cameraクラスのみ が使える新メソッド
  • Printerクラス(派生クラス)
    paper_size(紙のサイズ)を独自の属性として追加
    show をオーバーライドして、紙のサイズも表示
    print_doc メソッドは Printerクラスのみ が使える新メソッド

 実行結果としては、AlphaCam(Cameraオブジェクト)の情報が表示された後で shoot() の出力が、ProPrinter(Printerオブジェクト)については show() の出力と print_doc() の出力がそれぞれ確認できます。

まとめ

  • 派生クラスには、基底クラスに存在しない機能を新メソッドとして追加できる。
  • この新しいメソッドは、対応する派生クラスのオブジェクトに対してのみ呼び出せる。
  • 別の派生クラスに存在しないメソッドを呼び出すと、AttributeError(属性エラー)が発生する。
  • 共通機能は基底クラスに、特有機能は派生クラスにそれぞれ分割して実装することで、継承のメリットを活かしながらコードを分かりやすく保つことができる。

 以上のように、継承構造を整理しながら派生クラスで新しいメソッドを追加する手法は、オブジェクト指向プログラミングの可読性と拡張性を高める上で非常に重要です。