オブジェクト指向プログラミング(OOP)における継承は、既存のクラス(スーパークラスまたは親クラス)の属性やメソッドを新しいクラス(サブクラスまたは子クラス)に引き継ぐ仕組みです。これにより、コードの再利用性が向上し、クラス間の関係性を明確に表現することができます。このセクションでは、Pythonを用いてクラスの継承の基本概念と実装方法を初心者にもわかりやすく解説します。
継承は、既存のクラスの機能を新しいクラスに拡張・再利用するための仕組みです。継承を利用することで、コードの重複を避け、より整理された設計を行うことができます。
Pythonでは、サブクラスを定義する際に、スーパークラスの名前を括弧内に記述します。以下に、基本的な継承の構文と例を示します。
class スーパークラス:
# スーパークラスの定義
pass
class サブクラス(スーパークラス):
# サブクラスの定義
pass
以下に、Animal
クラスをスーパークラスとして、Dog
クラスをサブクラスとして継承する例を示します。
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
raise NotImplementedError("サブクラスでこのメソッドを実装してください。")
def move(self):
print(f"{self.name} は移動しています。")
class Dog(Animal):
def speak(self):
return f"{self.name} はワンワンと鳴きます。"
class Cat(Animal):
def speak(self):
return f"{self.name} はニャーニャーと鳴きます。"
Animal
:__init__
メソッドで name
属性を初期化します。speak
メソッドは、サブクラスで実装することを期待しています。move
メソッドは、全ての動物が移動する共通の動作を定義しています。
サブクラス Dog
と Cat
:
Animal
を継承しています。speak
メソッドをオーバーライドして、それぞれ犬と猫の鳴き声を定義しています。スーパークラスとサブクラスから生成されたオブジェクトを用いて、メソッドを呼び出す方法を見てみましょう。
# サブクラスのインスタンスを生成
dog = Dog("Buddy")
cat = Cat("Lucy")
# メソッドの呼び出し
print(dog.speak()) # 出力: Buddy はワンワンと鳴きます。
print(cat.speak()) # 出力: Lucy はニャーニャーと鳴きます。
# スーパークラスのメソッドを呼び出す
dog.move() # 出力: Buddy は移動しています。
cat.move() # 出力: Lucy は移動しています。
dog
と cat
は、それぞれ Dog
と Cat
クラスから生成されたオブジェクトです。speak
メソッドはサブクラスでオーバーライドされているため、各動物特有の鳴き声が出力されます。move
メソッドはスーパークラスで定義されているため、全ての動物オブジェクトで共通の動作として実行されます。super()
関数の使用super()
関数は、サブクラスからスーパークラスのメソッドや属性にアクセスするために使用されます。これにより、スーパークラスの機能を拡張・利用することが容易になります。
以下に、Dog
クラスでスーパークラスの __init__
メソッドを呼び出す例を示します。
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
raise NotImplementedError("サブクラスでこのメソッドを実装してください。")
def move(self):
print(f"{self.name} は移動しています。")
class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name) # スーパークラスのコンストラクタを呼び出す
self.breed = breed # サブクラス特有の属性を追加
def speak(self):
return f"{self.name} はワンワンと鳴きます。"
def fetch(self, item):
print(f"{self.name} は {item} を取りに行きます。")
super().__init__(name)
:Animal
の __init__
メソッドを呼び出し、name
属性を初期化します。これにより、サブクラスでスーパークラスの初期化処理を再利用できます。
サブクラス特有の属性 breed
:
Dog
クラスに特有の breed
属性を追加しています。
新しいメソッド fetch
:
# Dogクラスのインスタンスを生成
dog = Dog("Buddy", "Golden Retriever")
# メソッドの呼び出し
print(dog.speak()) # 出力: Buddy はワンワンと鳴きます。
dog.fetch("ボール") # 出力: Buddy は ボール を取りに行きます。
dog.move() # 出力: Buddy は移動しています。
# 属性のアクセス
print(dog.name) # 出力: Buddy
print(dog.breed) # 出力: Golden Retriever
Pythonでは、サブクラスが複数のスーパークラスを継承する多重継承が可能です。これにより、複数のクラスの機能を組み合わせて新しいクラスを作成することができます。ただし、多重継承は複雑さを増すため、慎重に使用する必要があります。
以下に、Flyable
と Swimmable
という2つのスーパークラスを継承する Duck
クラスの例を示します。
class Flyable:
def fly(self):
print(f"{self.name} は飛んでいます。")
class Swimmable:
def swim(self):
print(f"{self.name} は泳いでいます。")
class Duck(Animal, Flyable, Swimmable):
def speak(self):
return f"{self.name} はガーガーと鳴きます。"
def quack(self):
print(f"{self.name} がクワック!")
Flyable
と Swimmable
:それぞれ飛行能力と泳泳能力を提供するクラスです。
サブクラス Duck
:
Animal
、Flyable
、Swimmable
を継承しています。speak
メソッドをオーバーライドして、アヒル特有の鳴き声を定義しています。quack
を追加しています。# Duckクラスのインスタンスを生成
duck = Duck("Donald")
# メソッドの呼び出し
print(duck.speak()) # 出力: Donald はガーガーと鳴きます。
duck.fly() # 出力: Donald は飛んでいます。
duck.swim() # 出力: Donald は泳いでいます。
duck.quack() # 出力: Donald がクワック!
メソッドオーバーライドは、スーパークラスで定義されたメソッドをサブクラスで再定義することです。これにより、サブクラス固有の動作を実装することができます。
以下に、Animal
クラスの move
メソッドを Bird
クラスでオーバーライドする例を示します。
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
raise NotImplementedError("サブクラスでこのメソッドを実装してください。")
def move(self):
print(f"{self.name} は移動しています。")
class Bird(Animal):
def speak(self):
return f"{self.name} はチュンチュンと鳴きます。"
# moveメソッドをオーバーライド
def move(self):
print(f"{self.name} は飛び回っています。")
# Birdクラスのインスタンスを生成
bird = Bird("Tweety")
# メソッドの呼び出し
print(bird.speak()) # 出力: Tweety はチュンチュンと鳴きます。
bird.move() # 出力: Tweety は飛び回っています。
Animal
の move
メソッド:一般的な動物の移動動作を定義しています。
サブクラス Bird
での move
メソッドのオーバーライド:
isinstance
と issubclass
関数Pythonでは、オブジェクトが特定のクラスのインスタンスであるかどうか、またはクラスが特定のスーパークラスを継承しているかどうかを確認するために、isinstance
関数と issubclass
関数が提供されています。
isinstance
関数isinstance
関数は、オブジェクトが指定されたクラスのインスタンスであるかどうかを判断します。
# 使用例
dog = Dog("Buddy", 3)
print(isinstance(dog, Dog)) # 出力: True
print(isinstance(dog, Animal)) # 出力: True
print(isinstance(dog, Cat)) # 出力: False
issubclass
関数issubclass
関数は、あるクラスが指定されたスーパークラスを継承しているかどうかを判断します。
# 使用例
print(issubclass(Dog, Animal)) # 出力: True
print(issubclass(Cat, Animal)) # 出力: True
print(issubclass(Dog, Cat)) # 出力: False
isinstance(dog, Dog)
は、dog
が Dog
クラスのインスタンスであるため True
を返します。isinstance(dog, Animal)
は、Dog
クラスが Animal
クラスを継承しているため True
を返します。isinstance(dog, Cat)
は、dog
が Cat
クラスのインスタンスではないため False
を返します。issubclass(Dog, Animal)
は、Dog
が Animal
を継承しているため True
を返します。issubclass(Cat, Animal)
は、Cat
が Animal
を継承しているため True
を返します。issubclass(Dog, Cat)
は、Dog
が Cat
を継承していないため False
を返します。以下に、Car
クラスをスーパークラスとして、ElectricCar
クラスをサブクラスとして継承する例を示します。電気自動車固有の属性とメソッドを追加しています。
class Car:
def __init__(self, make, model, year):
self.make = make # インスタンス変数
self.model = model # インスタンス変数
self.year = year # インスタンス変数
self.odometer_reading = 0 # インスタンス変数
def description(self):
return f"{self.year} {self.make} {self.model}"
def read_odometer(self):
print(f"この車の走行距離は {self.odometer_reading} キロです。")
def update_odometer(self, mileage):
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("走行距離を巻き戻すことはできません。")
def increment_odometer(self, miles):
if miles >= 0:
self.odometer_reading += miles
else:
print("走行距離を減らすことはできません。")
class ElectricCar(Car):
def __init__(self, make, model, year, battery_size=75):
super().__init__(make, model, year) # スーパークラスのコンストラクタを呼び出す
self.battery_size = battery_size # サブクラス固有の属性
def describe_battery(self):
print(f"この車のバッテリー容量は {self.battery_size} kWh です。")
def fill_gas_tank(self):
print("この車はガソリンタンクを持っていません。")
Car
:走行距離を表示・更新・増加するメソッドを提供します。
サブクラス ElectricCar
:
Car
を継承しています。battery_size
を追加しています。describe_battery
メソッドを追加しています。fill_gas_tank
メソッドをオーバーライドしています。# ElectricCarクラスのインスタンスを生成
my_electric_car = ElectricCar("Tesla", "Model S", 2022, battery_size=100)
# メソッドの呼び出し
print(my_electric_car.description()) # 出力: 2022 Tesla Model S
my_electric_car.describe_battery() # 出力: この車のバッテリー容量は 100 kWh です。
my_electric_car.fill_gas_tank() # 出力: この車はガソリンタンクを持っていません。
# 走行距離の操作
my_electric_car.read_odometer() # 出力: この車の走行距離は 0 キロです。
my_electric_car.update_odometer(1500)
my_electric_car.read_odometer() # 出力: この車の走行距離は 1500 キロです。
my_electric_car.increment_odometer(500)
my_electric_car.read_odometer() # 出力: この車の走行距離は 2000 キロです。
super()
の使用:特にコンストラクタでスーパークラスの初期化を行う際に使用します。
メソッドオーバーライド:
必要に応じて、スーパークラスのメソッドを呼び出すことも可能です。
多重継承の注意:
super()
関数を利用することで、スーパークラスのメソッドを効率的に呼び出すことができます。実際にPythonコードを書いて継承を試し、スーパークラスとサブクラスの関係性を理解することで、オブジェクト指向プログラミングの基礎をさらに深めましょう。