オブジェクト指向でプログラミングをしていると、複数のクラスに対して共通性を持たせるために抽象クラス(Abstract)を作りたくなることがありませんか!?
Mayaerで身近なところですと、Qt(PySide/PyQt)の「QAbstractItemModel」「QAbstractSlider」等があります。特に装飾をせずに見よう見まね?でクラスを作ると、以下のようになっている場合があるかと思います。
class AbstractItem(object): def create(self): pass def delete(self): pass class MayaItem(AbstractItem): def create(self): pass item = MayaItem()
しかし!
抽象クラスの特徴として、以下の物があります。
- 抽象クラスからインスタンスを作成できない。
- オーバーライドが必須になっているメソッドがある。
残念ながら上記のコードでは、抽象クラスからインスタンスを作成してしまったり、オーバーライドの必須を強要することができません。。。名ばかりの抽象クラス。。。(´・ω・`)
そこで!
pythonの標準モジュールの「abc」を使います!抽象クラスを作る時のポイントになるのは、メタクラスと、デコレーションの設定です!(`・ω・´)ゞ
モジュールのimport
ネームスペースを書かないようにするのが一般的?なようなので、以下のようにimportすると良いと思います!
from abc import ABCMeta, abstractmethod
メタクラスの設定
抽象クラスにしたいクラスに、メタクラス「ABCMeta」を設定します。これを忘れると、うまく抽象クラスにすることができません(´・ω・`)
from abc import ABCMeta, abstractmethod class AbstractItem(object): __metaclass__ = ABCMeta def create(self): pass def delete(self): pass
続いて、オーバーライドが必須としたいメソットにデコレーション「@abstractmethod」を設定していきます。今回は「create」と「delete」両方とも設定したいと思います。
from abc import ABCMeta, abstractmethod class AbstractItem(object): __metaclass__ = ABCMeta @abstractmethod def create(self): pass @abstractmethod def delete(self): pass
すると!「AbstractItem」のインスタンスを作ろうとすると、以下のようにエラーします(*´ω`*)b
item = AbstractItem() # Error: Can't instantiate abstract class AbstractItem with abstract methods create, delete
続いて!「AbstractItem」を継承した「MayaItem」を作成します。ここではあえて、メソッド「delete」を実装しないようにしてみます。
from abc import ABCMeta, abstractmethod class AbstractItem(object): __metaclass__ = ABCMeta @abstractmethod def create(self): pass @abstractmethod def delete(self): pass class MayaItem(AbstractItem): def create(self): pass
インスタンスを作ろうとすると、、、
item = MayaItem() # Error: Can't instantiate abstract class MayaItem with abstract methods delete
不完全な継承をしていると、きっちりエラーを吐いてくれます!(ホントはインスタンス作る前にエラーしてほしいけど・・・)
これで、Pythonでもキッチリとした抽象クラスが作れると思います!(`・ω・´)ゞ