Pythonで抽象クラス・抽象メソッドを使う(abc.ABC, abc.abstractmethod)
この記事では、Pythonで抽象クラスと抽象メソッドを`abc`モジュールを使って定義する方法を解説します。抽象クラスとは、具体的な実装を持たないクラスで、サブクラスで実装が必須となるメソッドを定義できます。
目次
抽象クラスと抽象メソッドの概要
抽象クラスとは、具体的な実装を持たず、サブクラスで実装されることを想定したメソッドを持つクラスです。抽象メソッドは、抽象クラス内で宣言され、サブクラスが必ず実装しなければならないメソッドです。これにより、クラス間の共通インターフェースを定義し、コードの再利用性と保守性を高めることができます。
Pythonでは、`abc`モジュール(Abstract Base Classes)を使用して抽象クラスと抽象メソッドを定義します。`abc.ABC`クラスを継承して抽象クラスを作成し、`abc.abstractmethod`デコレータで抽象メソッドを定義します。
abc.ABCとabc.abstractmethodの使い方
以下の手順で抽象クラスと抽象メソッドを定義します。
from abc import ABC, abstractmethod
class AbstractClass(ABC):
@abstractmethod
def abstract_method(self):
pass
class ConcreteClass(AbstractClass):
def abstract_method(self):
print("ConcreteClassのabstract_methodが実行されました")
object = ConcreteClass()
object.abstract_method()
`abc.ABC`を継承した`AbstractClass`は抽象クラスです。`abstract_method`は`@abstractmethod`デコレータによって抽象メソッドとして定義されています。`ConcreteClass`は`AbstractClass`を継承し、`abstract_method`を実装しています。抽象メソッドを実装せずに抽象クラスをインスタンス化しようとすると、`TypeError`が発生します。
サンプルコード:図形クラスの例
図形の面積と周囲長を求めるクラスを例に、抽象クラスと抽象メソッドの使い方を見てみましょう。
from abc import ABC, abstractmethod
import math
class Shape(ABC):
@abstractmethod
def area(self):
pass
@abstractmethod
def perimeter(self):
pass
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
return math.pi * self.radius**2
def perimeter(self):
return 2 * math.pi * self.radius
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
def perimeter(self):
return 2 * (self.width + self.height)
circle = Circle(5)
print(f"円の面積: {circle.area()}")
print(f"円の周囲長: {circle.perimeter()}")
rectangle = Rectangle(4, 6)
print(f"長方形の面積: {rectangle.area()}")
print(f"長方形の周囲長: {rectangle.perimeter()}")
この例では、`Shape`クラスが抽象クラスとして定義され、`area`と`perimeter`が抽象メソッドとして定義されています。`Circle`と`Rectangle`クラスは`Shape`クラスを継承し、それぞれの図形に応じた面積と周囲長の計算を実装しています。
継承と多態性
抽象クラスと抽象メソッドを使うことで、継承と多態性を効果的に活用できます。多態性とは、異なるクラスのオブジェクトに対して同じメソッドを呼び出した場合、それぞれのクラスで定義されたメソッドが実行されるという性質です。抽象クラスを基底クラスとして、複数のサブクラスを作成することで、共通のインターフェースを維持しつつ、各サブクラス固有の機能を実装できます。