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

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

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

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

"collections.abc" サブモジュールには ABC から派生した具象クラスがいく
つかあります。 もちろん、このクラスから、さらに派生させることもできま
す。 また "collections.abs" サブモジュールにはいくつかの ABC もあって
、あるクラスやインスタンスが特定のインタフェースを提供しているかどうか
、たとえば、ハッシュ可能なのかやマッピングなのか、をテストできます。

このモジュールは、 抽象基底クラスを定義するためのメタクラス "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

   バージョン 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 のサブクラスと見なせるかどうかチェックしま
      す。これによって ABC のサブクラスと見なしたい全てのクラスについ
      て "register()" を呼び出すことなく "issubclass" の振る舞いをさら
      にカスタマイズできます。 (このクラスメソッドは 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__()" の意味は、
   "__iter__()" メソッドがクラスの(または "__mro__" でアクセスされる基
   底クラスの一つの) "__dict__" にある場合にもそのクラスが
   "MyIterable" だと見なされるということです。

   最後に、一番下の行は "Foo" を "__iter__()" メソッドを定義しないにも
   かかわらず "MyIterable" の仮想的サブクラスにします("Foo" は古い様式
   の "__len__()" と "__getitem__()" を用いたイテレータプロトコルを使
   っています。)。これによって "Foo" のメソッドとして "get_iterator"
   が手に入るわけではないことに注意してください。それは別に提供されて
   います。

"abc" モジュールは以下のデコレータも提供しています:

@abc.abstractmethod

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

   このデコレータを使うには、クラスのメタクラスが "ABCMeta" かそれを継
   承したものである必要があります。 "ABCMeta" の派生クラスをメタクラス
   に持つクラスは、全ての抽象メソッドとプロパティをオーバーロードしな
   い限りインスタンス化することができません。抽象メソッドは通常の
   'super' 呼び出し方法で呼ぶことができます。 "abstractmethod()" はプ
   ロパティやデスクリプタのために抽象メソッドを定義することもできます
   。

   クラスに動的に抽象メソッドを追加する、あるいはメソッドやクラスが作
   られた後から抽象的かどうかの状態を変更しようと試みることは、サポー
   トされません。 "abstractmethod()" が影響を与えるのは正規の継承によ
   り派生したサブクラスのみで、ABC の "register()" メソッドで登録され
   た "仮想的サブクラス" は影響されません。

   "abstractmethod()" が他のメソッドデスクリプタと組み合わされる場合、
   次の例のように、一番内側のデコレータとして適用しなければなりません:

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

          @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)

   デスクリプタをABC 機構と協調させるために、デスクリプタは
   "__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

   バージョン 3.2 で追加.

   バージョン 3.3 で非推奨: "classmethod" を "abstractmethod()" と一緒
   に使えるようになったため、このデコレータは冗長になりました。

   組み込みの "classmethod()" のサブクラスで、抽象クラスメソッドである
   ことを示します。それ以外は "abstractmethod()" と同じです。

   この特殊ケースは "classmethod()" デコレータが抽象メソッドに適用され
   た場合に抽象的だと正しく認識されるようになったため撤廃されます:

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

@abc.abstractstaticmethod

   バージョン 3.2 で追加.

   バージョン 3.3 で非推奨: "staticmethod" を "abstractmethod()" と一
   緒に使えるようになったため、このデコレータは冗長になりました。

   組み込みの "staticmethod()" のサブクラスで、抽象静的メソッドである
   ことを示します。それ以外は "abstractmethod()" と同じです。

   この特殊ケースは "staticmethod()" デコレータが抽象メソッドに適用さ
   れた場合に抽象的だと正しく認識されるようになったため撤廃されます:

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

@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()" の呼び出しごとに、トーク
   ンは変更されます。

   バージョン 3.4 で追加.

-[ 脚注 ]-

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