プログラミングにおける interface と抽象クラスの違い
オブジェクト指向プログラミングでは、interface と 抽象クラス は、クラスの「契約」や共通の振る舞いを定義するための手段ですが、以下の点で異なります。
基本概念
Interface (インターフェース)
-
定義:
インターフェースは、クラスが実装すべきメソッドのシグネチャ(名前、引数、戻り値)だけを定義します。
実装の詳細は持たず、実装する側に「こういう動作を提供してください」という契約を強制します。 -
特徴:
- メソッドのシグネチャのみを規定する
- 共通の実装や状態(フィールド)は持たない
- 多重継承の形で複数のインターフェースを実装できる場合が多い
抽象クラス (Abstract Class)
-
定義:
抽象クラスは、インターフェースのように契約を定義するだけでなく、一部のメソッドにデフォルトの実装を提供したり、共通の状態(フィールド)を持ったりすることができます。
継承先のクラスは、抽象クラスの抽象メソッドを必ず実装する必要があります。 -
特徴:
- 抽象メソッドを含み、サブクラスに実装を強制する
- デフォルトの実装や共通のプロパティを持つことができる
- 単一継承が一般的(言語によっては複数継承がサポートされる場合もある)
Python における実装例
Python には明示的な interface
キーワードはありませんが、abc
モジュールを使って抽象基底クラス(Abstract Base Class; ABC)を定義することで、インターフェースや抽象クラスのような振る舞いを実現できます。
インターフェース風の抽象基底クラス
from abc import ABC, abstractmethod
class IShape(ABC):
@abstractmethod
def area(self) -> float:
"""面積を計算して返すメソッド"""
pass
@abstractmethod
def perimeter(self) -> float:
"""周囲長を計算して返すメソッド"""
pass
- ポイント:
- IShape はあくまでメソッドのシグネチャのみを定義し、実装は提供しません。
- これにより、IShape を実装するクラスは area() と perimeter() の実装を必ず提供する必要があります。
- これは、インターフェースとしての役割に相当します。
抽象クラス
from abc import ABC, abstractmethod
class Shape(ABC):
def __init__(self, name: str):
self.name = name
@abstractmethod
def area(self) -> float:
"""面積を計算して返すメソッド(サブクラスで実装)"""
pass
def describe(self):
"""共通の振る舞い: 図形の名前と面積を表示する"""
print(f"{self.name} の面積は {self.area()} です。")
class Rectangle(Shape):
def __init__(self, width: float, height: float):
super().__init__("Rectangle")
self.width = width
self.height = height
def area(self) -> float:
return self.width * self.height
# 使用例
rect = Rectangle(5, 10)
rect.describe() # 出力例: Rectangle の面積は 50 です。
- ポイント:
- Shape は抽象クラスとして、area() の抽象メソッドを定義し、describe() といった共通の振る舞いを実装しています。
- Rectangle は Shape を継承し、area() を実装することで具体的なクラスとなります。
まとめ
- interface(インターフェース)
- メソッドのシグネチャのみを定義し、実装を持たない。
- 実装クラスは全てのメソッドを実装する必要がある。
- Python では、abc モジュールで抽象基底クラスを使い、インターフェースのように振る舞わせることができる。
- 抽象クラス (Abstract Class)
- 一部のメソッドにデフォルト実装や共通の状態を持たせることができる。
- 抽象メソッドを定義し、サブクラスに実装を強制する。