抽象クラスA
をデフォルトの動作を持つコンストラクターで宣言しようとしています。すべてのサブクラスはメンバーself.n
を初期化する必要があります。
from abc import ABCMeta
class A(object):
__metaclass__ = ABCMeta
def __init__(self, n):
self.n = n
ただし、A
クラスはインスタンス化されません。これは、抽象クラスであるためです。問題は、これが実際に許可されていることです:
a = A(3)
期待どおりにエラーが発生することはありません。
だから:コンストラクタのデフォルトの動作を定義しながら、インスタンス化できない抽象クラスをどのように定義できますか?
__init__
抽象メソッド:
from abc import ABCMeta, abstractmethod
class A(object):
__metaclass__ = ABCMeta
@abstractmethod
def __init__(self, n):
self.n = n
if __name__ == '__main__':
a = A(3)
役立ちます:
TypeError: Can't instantiate abstract class A with abstract methods __init__
Python 3バージョン:
from abc import ABCMeta, abstractmethod
class A(object, metaclass=ABCMeta):
@abstractmethod
def __init__(self, n):
self.n = n
if __name__ == '__main__':
a = A(3)
同様に動作します:
TypeError: Can't instantiate abstract class A with abstract methods __init__
@abc.abstractmethod
デコレータを使用して、メソッドを抽象として定義する必要があります。
__new__
メソッドをオーバーライドして、直接インスタンス化を防ぐことができます。
class A(object):
__metaclass__ = ABCMeta
def __new__(cls, *args, **kwargs):
if cls is A:
raise TypeError(
"TypeError: Can't instantiate abstract class {name} directly".format(name=cls.__name__)
)
return object.__new__(cls)
出力:
>>> A()
Traceback (most recent call last):
File "<ipython-input-8-3cd318a12eea>", line 1, in <module>
A()
File "/Users/ashwini/py/so.py", line 11, in __new__
"TypeError: Can't instantiate abstract class {name} directly".format(name=cls.__name__)
TypeError: TypeError: Can't instantiate abstract class A directly
それほどエレガントではない解決策はこれです:
class A(object):
def __init__(self, n):
if self.__class__ == A:
raise Exception('I am abstract!')
self.n = n
使用法
class B(A):
pass
a = A(1) # Will throw exception
b = B(1) # Works fine as expected.