"abc" --- 抽象基底クラス
************************

**ソースコード:** Lib/abc.py

======================================================================

このモジュールは Python に **PEP 3119** で概要が示された *抽象基底クラ
ス* (ABC) を定義する基盤を提供します。なぜこれが Python に付け加えられ
たかについてはその PEP を参照してください。 (ABC に基づいた数の型階層
を扱った **PEP 3141** と "numbers" モジュールも参照してください。)

"collections" モジュール には、抽象基底クラス から派生するいくつかの具
象クラスがある。もちろん、これらはさらに派生させることができる。さらに
、 "collections.abc" サブモジュールには、クラスやインスタンス が特定の
インターフェース 、たとえば 、 *hashable* であるか、 *mapping* である
かをテストするために使用できる抽象基底クラス があります。

このモジュールは、 抽象基底クラスを定義するためのメタクラス "ABCMeta"
と、 継承を利用して抽象基底クラスを代替的に定義するヘルパークラス
"ABC" を提供します。

class abc.ABC

   メタクラスとして "ABCMeta" を持つヘルパークラスです。このクラスを使
   うことで、"ABC" を継承するだけで抽象基底クラスを作成でき、しばしば
   混乱しがちなメタクラスの使用を避けることができます。例えば:

      from abc import ABC

      class MyABC(ABC):
          pass

   "ABC" の型は "ABCMeta" なので、"ABC" を継承する場合も、メタクラスを
   使う際の通常の注意が必要です。 多重継承ではメタクラスが競合する場合
   があります。 また、"metaclass" キーワードに "ABCMeta" を直接指定し
   て、抽象基底クラスを定義することもできます。

      from abc import ABCMeta

      class MyABC(metaclass=ABCMeta):
          pass

   Added in version 3.4.

class abc.ABCMeta

   抽象基底クラス(ABC)を定義するためのメタクラス。

   ABC を作るときにこのメタクラスを使います。ABC は直接的にサブクラス
   化することができ、ミックスイン(mix-in)クラスのように振る舞います。
   また、無関係な具象クラス(組み込み型でも構いません)と無関係な ABC を
   "仮想的サブクラス" として登録できます -- これらとその子孫は組み込み
   関数 "issubclass()" によって登録した ABC のサブクラスと判定されます
   が、登録した ABC は MRO (Method Resolution Order, メソッド解決順)に
   は現れませんし、この ABC のメソッド実装が("super()" を通してだけで
   なく)呼び出し可能になるわけでもありません。 [1]

   メタクラスが "ABCMeta" のクラスには、次のメソッドがあります。

   register(subclass)

      *subclass* を "仮想的サブクラス" としてこの ABC に登録します。た
      とえば:

         from abc import ABC

         class MyABC(ABC):
             pass

         MyABC.register(tuple)

         assert issubclass(tuple, MyABC)
         assert isinstance((), MyABC)

      バージョン 3.3 で変更: クラスデコレータとして使うことができるよ
      うに、登録されたサブクラスを返します。

      バージョン 3.4 で変更: "register()" の呼び出しを検出するには、
      "get_cache_token()" 関数を使えます。

   また、次のメソッドを抽象基底クラスの中でオーバーライドできます:

   __subclasshook__(subclass)

      (クラスメソッドとして定義しなければなりません。)

      "subclass" がこの ABC のサブクラスとみなされるか調べます。 この
      メソッドで "issubclass()" の動作をさらにカスタマイズすれば、ABC
      のサブクラスとみなしたいクラスごとに "register()" を呼ぶ必要がな
      くなります。 (このクラスメソッドは、ABC の "__subclasscheck__()"
      メソッドから呼び出されます。)

      このメソッドは "True"、"False"、"NotImplemented" のいずれかを返
      す必要があります。 "True" を返すと、"subclass" はこの ABC のサブ
      クラスとみなされます。 "False" を返すと、通常ならサブクラスであ
      っても、"subclass" はこの ABC のサブクラスとはみなされません。
      "NotImplemented" を返すと、通常の仕組みでサブクラスの検査を続け
      ます。

   この概念のデモとして、次の ABC 定義の例を見てください:

      class Foo:
          def __getitem__(self, index):
              ...
          def __len__(self):
              ...
          def get_iterator(self):
              return iter(self)

      class MyIterable(ABC):

          @abstractmethod
          def __iter__(self):
              while False:
                  yield None

          def get_iterator(self):
              return self.__iter__()

          @classmethod
          def __subclasshook__(cls, C):
              if cls is MyIterable:
                  if any("__iter__" in B.__dict__ for B in C.__mro__):
                      return True
              return NotImplemented

      MyIterable.register(Foo)

   ABC "MyIterable" は、イテラブルの標準的なメソッド "__iter__()" を抽
   象メソッドとして定義しています。 ここで定義した実装は、サブクラスか
   ら呼び出すこともできます。 "get_iterator()" メソッドも抽象基底クラ
   ス "MyIterable" の一部ですが、抽象クラスではない派生クラスでオーバ
   ーライドする必要はありません。

   ここで定義したクラスメソッド "__subclasshook__()" は、"__dict__" に
   "__iter__()" メソッドを持つクラスを "MyIterable" とみなします。 ま
   た、"__mro__" リストからたどれる基底クラスのいずれかがそのメソッド
   を持つ場合も、同様にみなします。

   最後の行では、"__iter__()" メソッドを定義していない "Foo" も、
   "MyIterable" の仮想的サブクラスにしています ("Foo" は "__len__()"
   と "__getitem__()" に基づく古いイテラブルプロトコルを使っています)
   。 ただし、これによって "get_iterator" が "Foo" のメソッドとして使
   えるようになるわけではないので、別途定義しています。

"abc" モジュールは、次のデコレータも提供します。

@abc.abstractmethod

   抽象メソッドを示すデコレータです。

   このデコレータを使うには、クラスのメタクラスが "ABCMeta" またはその
   派生クラスである必要があります。 メタクラスが "ABCMeta" から派生し
   ているクラスは、すべての抽象メソッドと抽象プロパティがオーバーライ
   ドされるまで、インスタンス化できません。 抽象メソッドは、通常の
   super 呼び出しの仕組みで呼び出せます。 "@abstractmethod" は、プロパ
   ティやデスクリプタの抽象メソッドを宣言するためにも使えます。

   クラスへの抽象メソッドの動的な追加や、作成済みのメソッドやクラスが
   抽象であるかどうかの変更は、"update_abstractmethods()" 関数を使う場
   合にのみサポートされます。 "@abstractmethod" が影響するのは、通常の
   継承によるサブクラスだけです。 ABC の "register()" メソッドで登録さ
   れた「仮想的サブクラス」には影響しません。

   "@abstractmethod" を他のメソッドデスクリプタと組み合わせる場合は、
   次の例のように最も内側のデコレータとして適用してください。

      class C(ABC):
          @abstractmethod
          def my_abstract_method(self, arg1):
              ...
          @classmethod
          @abstractmethod
          def my_abstract_classmethod(cls, arg2):
              ...
          @staticmethod
          @abstractmethod
          def my_abstract_staticmethod(arg3):
              ...

          @property
          @abstractmethod
          def my_abstract_property(self):
              ...
          @my_abstract_property.setter
          @abstractmethod
          def my_abstract_property(self, val):
              ...

          @abstractmethod
          def _get_x(self):
              ...
          @abstractmethod
          def _set_x(self, val):
              ...
          x = property(_get_x, _set_x)

   抽象基底クラスの仕組みと正しく連携するには、デスクリプタが抽象であ
   ることを "__isabstractmethod__" で示す必要があります。 一般に、デス
   クリプタを構成するメソッドのいずれかが抽象なら、この属性を "True"
   にするべきです。 例えば、Python の組み込み "@property" は次と同等の
   処理を行います。

      class Descriptor:
          ...
          @property
          def __isabstractmethod__(self):
              return any(getattr(f, '__isabstractmethod__', False) for
                         f in (self._fget, self._fset, self._fdel))

   注釈:

     Java の抽象メソッドと違い、これらの抽象メソッドは実装を持ち得ます
     。この実装は "super()" メカニズムを通してそれをオーバーライドした
     クラスから呼び出すことができます。これは協調的多重継承を使ったフ
     レームワークにおいて super 呼び出しの終点として有効です。

"abc" モジュールは、次の古いデコレータもサポートしています。

@abc.abstractclassmethod

   Added in version 3.2.

   バージョン 3.3 で非推奨: "@classmethod" と "@abstractmethod" を組み
   合わせて使えるようになったため、このデコレータは不要になりました。

   抽象クラスメソッドを表す、組み込みの "classmethod" のサブクラスです
   。 それ以外の点では "@abstractmethod" と同様です。

   抽象メソッドに "@classmethod" デコレータを適用すれば、抽象であると
   正しく認識されるようになったため、この特別なデコレータは非推奨です
   。

      class C(ABC):
          @classmethod
          @abstractmethod
          def my_abstract_classmethod(cls, arg):
              ...

@abc.abstractstaticmethod

   Added in version 3.2.

   バージョン 3.3 で非推奨: "@staticmethod" と "@abstractmethod" を組
   み合わせて使えるようになったため、このデコレータは不要になりました
   。

   抽象静的メソッドを表す、組み込みの "staticmethod" のサブクラスです
   。 それ以外の点では "@abstractmethod" と同様です。

   抽象メソッドに "@staticmethod" デコレータを適用すれば、抽象であると
   正しく認識されるようになったため、この特別なデコレータは非推奨です
   。

      class C(ABC):
          @staticmethod
          @abstractmethod
          def my_abstract_staticmethod(arg):
              ...

@abc.abstractproperty

   バージョン 3.3 で非推奨: "@property"、"@property.getter"、
   "@property.setter"、"@property.deleter" を "@abstractmethod" と組み
   合わせて使えるようになったため、このデコレータは不要になりました。

   抽象プロパティを表す、組み込みの "property" のサブクラスです。

   抽象メソッドに "@property" デコレータを適用すれば、抽象であると正し
   く認識されるようになったため、この特別なデコレータは非推奨です。

      class C(ABC):
          @property
          @abstractmethod
          def my_abstract_property(self):
              ...

   この例は読み出し専用のプロパティを定義しています。プロパティを構成
   するメソッドの1つ以上を abstract にすることで、読み書きできる抽象プ
   ロパティを定義することができます:

      class C(ABC):
          @property
          def x(self):
              ...

          @x.setter
          @abstractmethod
          def x(self, val):
              ...

   構成するメソッド全てが abstract でない場合、abstract と定義されたメ
   ソッドのみが、具象サブクラスによってオーバーライドする必要がありま
   す:

      class D(C):
          @C.x.setter
          def x(self, val):
              ...

"abc" モジュールは、次の関数も提供します。

abc.get_cache_token()

   現在の抽象基底クラスのキャッシュトークンを返します。

   このトークンは、仮想サブクラスのための抽象基底クラスの現在のバージ
   ョンを特定する (等価性検査をサポートしている) 不透明なオブジェクト
   です。 任意のABCでの "ABCMeta.register()" の呼び出しごとに、トーク
   ンは変更されます。

   Added in version 3.4.

abc.update_abstractmethods(cls)

   抽象クラスが抽象であるかどうかを再計算する関数です。 クラスを作成し
   た後で、その抽象メソッドを実装したり変更したりした場合に呼び出して
   ください。 通常はクラスデコレータの中から呼び出します。

   クラスデコレータとして使えるように、"cls" を返します。

   "cls" が "ABCMeta" のインスタンスでなければ、何もしません。

   注釈:

     この関数は、"cls" のスーパークラスがすでに更新されていることを前
     提とします。 サブクラスの更新は行いません。

   Added in version 3.10.

-[ 脚注 ]-

[1] C++ プログラマは Python の仮想的基底クラスの概念は C++ のものと同
    じではないということを銘記すべきです。
