【Python】クラスの継承とダックタイピング(インターフェース)

Python

本記事ではPythonにおけるクラス宣言、継承、インターフェースとして使えるダックタイピングについて紹介します。

継承

概要

既存のクラスの特徴をもつ新しいクラスをつくる仕組みです。

(例)過去に「動物」クラスを作ったことがあるとして、その特徴を継承した「犬」クラスと「猫」クラスを作る。

サンプル

動物と犬猫の継承関係のサンプルです。この例では「動物は鳴くもの」という特徴を持っていて、犬と猫も同様の特徴(機能)を受け継ぎます。

Python3用のサンプルコード

#coding: UTF-8

# 動物を表す基本クラス
class Animal:  # Python3では明示的なobjectの継承は記述不要
    def __init__(self, name):
        self.name = name  # インスタンス変数

    def make_sound(self):
        print("動物の声を出す")  # 基本クラスのメソッド

# 犬クラス(Animalクラスを継承)
class Dog(Animal):  # 継承を表す
    def make_sound(self):  # メソッドのオーバーライド
        print(self.name + "の鳴き声: ワン!")

# 猫クラス(Animalクラスを継承)
class Cat(Animal):  # 継承を表す
    def make_sound(self):  # メソッドのオーバーライド
        print(self.name + "の鳴き声: ニャーン!")

def main():
    dog = Dog("ポチ")  # 犬オブジェクトを生成
    cat = Cat("たま")  # 猫オブジェクトを生成

    #-------------------------------
    # 動物を個別に鳴かせる
    #-------------------------------
    print("-- 個別に鳴かせる --")
    dog.make_sound()  # 犬クラスを鳴かせる
    cat.make_sound()  # 猫クラスを鳴かせる

    #-------------------------------
    # 動物をまとめて鳴かせる
    #-------------------------------
    print("-- まとめて鳴かせる --")

    # 動物という括りでリストにまとめる
    animal_list = [dog, cat]  # リストを使う

    # リストに含まれる動物をすべて鳴かせる
    for animal in animal_list:
        animal.make_sound()

if __name__ == "__main__":
    main()

実行結果

-- 個別に鳴かせる --
ポチの鳴き声: ワン!
たまの鳴き声: ニャーン!
-- まとめて鳴かせる --
ポチの鳴き声: ワン!
たまの鳴き声: ニャーン!

Python2用のサンプルコード

Python2では、基本クラスの宣言に明示的にobjectを継承する必要がある点に注意してください。

#coding: UTF-8

# 動物を表す基本クラス
class Animal(object):  # Python2では明示的にobjectを継承 ★
    # 以下省略。

ダックタイピング(インターフェース)

PythonにはC#などのインターフェースと全く同じ概念はありませんが、似たような目的を達成するために「ダックタイピング」を使うことができます。「ダックタイピング」とは「もし鳥がアヒルのように歩き、アヒルのように鳴くなら、その鳥はアヒルである」という考え方に基づいています。つまり、オブジェクトの型よりも、そのオブジェクトが持つメソッドや振る舞いが重要であるという考え方です。

概要

「ダックタイピング」により異なるクラスに共通の機能を持たせることができます。それぞれのクラスが共通のベースクラスを持つ必要はありません。

(例)「電気自動車」クラスと「テレビ」クラスは、どちらも「電源をONする」というメソッド(機能)を外部に公開する。

サンプル

Python3用のサンプルコード

#coding: UTF-8

class ElectricCar:
    def drive(self):
        print("電気自動車:走ります。")

    def turn_on(self):
        print("電気自動車:スイッチをオンにしました。")

    def turn_off(self):
        print("電気自動車:スイッチをオフにしました。")

class Television:
    def operate(self):
        print("テレビ:映像を映します。")

    def turn_on(self):
        print("テレビ:スイッチをオンにしました。")

    def turn_off(self):
        print("テレビ:スイッチをオフにしました。")

def main():
    # 電気自動車
    electric_car = ElectricCar()
    # テレビ
    television = Television()

    #-------------------------------
    # 電源をまとめてON
    #-------------------------------
    print("-- まとめて電源ON --")

    # 電源スイッチを有するオブジェクトでまとめる
    switchable_list = [electric_car, television]

    # リストに含まれる機器の電源をすべてONする
    for switchable in switchable_list:
        switchable.turn_on()

    #-------------------------------
    # 機器を使用
    #-------------------------------
    print("-- 機器を使用 --")
    electric_car.drive()     # 電気自動車を運転
    television.operate()     # テレビを操作

if __name__ == "__main__":
    main()

実行結果

-- まとめて電源ON --
電気自動車:スイッチをオンにしました。
テレビ:スイッチをオンにしました。
-- 機器を使用 --
電気自動車:走ります。
テレビ:映像を映します。

Python2用のサンプルコード

Python2では、基本クラスの宣言に明示的にobjectを継承する必要がある点に注意してください。

#coding: UTF-8

class ElectricCar(object):  # Python2では明示的にobjectを継承 ★
    # 以下省略

まとめ

本記事ではPythonにおけるクラス宣言、継承、ダックタイピングについて紹介しました。動物→犬・猫のようにベースと派生の関係がある場合は継承、なるクラスに共通の機能を持たせる場合は共通の名前を持つメソッドを実装するようにしましょう。

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