web-dev-qa-db-ja.com

抽象クラスの代わりにNotImplementedErrorを使用する

MyBaseは、すべての子でメソッドf()の実装を強制しています。これは、 _abc.ABCMeta_ を使用してf()abstractmethodにすることで実現できます。

_import abc


class MyBase(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def f(self, x):
        pass

class Child1(MyBase):
    def f(self, x):
        print(x)

class Child2(MyBase):
    pass

Child1().f(4)   # prints 4
Child2().f(4)   # TypeError: Can't instantiate abstract class Child2 with abstract methods f
MyBase()        # TypeError: Can't instantiate abstract class MyBase with abstract methods f
_

..または、代わりに NotImplementedError による:

_class MyBase():

    def f(self, x):
        raise NotImplementedError('Abstract method not implemented.')

class Child1(MyBase):
    def f(self, x):
        print(x)

class Child2(MyBase):
    pass

Child1().f(4)   # prints 4
Child2().f(4)   # raises implementation error
MyBase()        # does NOT raise error
_

NotImplementedErrorを返す代わりに抽象クラスを使用すると、たとえばMyBase()の偶発的なインスタンス化が禁止されます。

NotImplementedErrorよりも抽象クラスを使用することによる他の利点(または欠点)はありますか?

5
Fermi paradox

抽象クラスを使用する必要があるのは、それがモデルに適切な選択であるためであり、望ましい副作用があるためではありません。したがって、利益を考える代わりに、意味を考えてください。

抽象クラスはクラスを分類し、そのクラスのグループに共通のデータと動作をグループ化できるようにします。それが問題ドメインに当てはまる場合(共通のプロパティを持つ複数のクラスを認識している場合)、抽象クラスを使用します。そうではなく、実装者に実装を完了するようにヒントを与えるだけの場合は、テンプレートなどを作成して例外をスローします。

抽象クラスのインスタンスを作成できないことは、事の「欠点」ではなく、その目的に固有のものです。

6
Martin Maat

「抽象クラス」は一般的なプログラミングの概念です。プログラミング概念としての抽象クラスは、決してインスタンス化されるべきではないクラスですまったくですが、別のクラスの基本クラスとしてのみ使用されるべきです。

一部の言語では、クラスが抽象であることを明示的に指定できます。たとえば、C++では、実装がないとマークされた仮想メソッドを持つクラス。一部の言語では、そのようなことはありません。

言語で許可されている場合は、抽象クラスを明示的に抽象としてマークする方法で抽象クラスを記述します。そうでない場合は、抽象クラスのインスタンス化を検出できる他の方法を使用するか、抽象クラスのインスタンスを使用しても使用可能な結果が得られない可能性があるため、問題を無視してください。

2
gnasher729