以下の2つのクラスを作ると想定します。
class Calc1():
def calc(self, a, b):
c = a + b
return c
class Calc2():
def calc(self, a, b):
c = a - b
return c
次のように使う予定です。
l = [Calc1(), Calc2(), Calc1(), Calc2()]
for calc in l:
print(calc.calc())
こういった使い方をする場合、2つのクラスには calc()
メソッドが必須です。
しかし久しぶりに新しい Calc3
クラスを作る際、calc
の実装を忘れてしまうかもしれません。
単純なプログラムならエラーを見てすぐに実装を忘れていたことに気付けるかもしれませんが、なるべく想定外の事態は避けたいです。
そんなときには abstract
を使いましょう!
abstractの使い方
abstract を使って継承前提のクラスを作成することができます。
定義の仕方は以下です。
from abc import ABC
class _Calc_template(ABC):
pass
class _Calc_template(metaclass=ABCMeta):
pass
どちらを使っても同じです。ABC
は中に metaclass=ABCMeta
が書かれているだけなので...
デコレータ @abstractmethod
を使って抽象メソッドを定義します。
class _Calc_template(ABC):
@abstractmethod
def calc() -> float:
pass
矢印で ->
返り値の型を明確にしておくことで、エディターの補間が働くようになるので便利です。(abstractに限らず)
抽象クラスを継承したクラスで、メソッドの定義をせずにインスタンスを作ろうとするとエラーが出ます。
class Calc3(_Calc_template):
pass
Calc3()
# >>> TypeError: Can't instantiate abstract class Calc3 with abstract method calc
変数定義はちょっと微妙?
デコレータは関数にしか使えませんが、Pythonでは関数の形でクラス変数を定義できます。ゲッター・セッターでGoogle検索すれば出てきます。
使い方
class _Calc_template(ABC):
@property
@abstractmethod
def hoge():
pass
動作
class Calc3(_Calc_template):
pass
Calc3()
# >>> TypeError: Can't instantiate abstract class Calc3 with abstract method hoge
class Calc3(_Calc_template):
hoge = 0
def __init__(self, h):
self.hoge = h
Calc3()
# エラーなし
しかし以下だとエラーが出る。
class Calc3(_Calc_template):
def __init__(self, h):
self.hoge = h
Calc3()
# >>> TypeError: Can't instantiate abstract class Calc3 with abstract method hoge
クラス変数があればインスタンス変数がなくても通ってしまう。
class Calc3(_Calc_template):
hoge = -1
Calc3()
# エラーなし
純粋にインスタンス変数の作成を強制できる方法を知っている方がいればぜひ教えてください...