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

バージョン 2.6 で追加.

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

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

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

The "collections" module has some concrete classes that derive from
ABCs; these can, of course, be further derived. In addition, the
"collections" module has some ABCs that can be used to test whether a
class or instance provides a particular interface, for example, if it
is hashable or if it is a mapping.

このモジュールは以下のクラスを提供します:

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 ABCMeta

         class MyABC:
             __metaclass__ = ABCMeta

         MyABC.register(tuple)

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

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

   __subclasshook__(subclass)

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

      *subclass* がこの ABC のサブクラスと見なせるかどうかチェックしま
      す。これによって ABC のサブクラスと見なしたい全てのクラスについ
      て "register()" を呼び出すことなく "issubclass" の振る舞いをさら
      にカスタマイズできます。 (このクラスメソッドは ABC の
      "__subclasscheck__()" メソッドから呼び出されます。)

      このメソッドは "True", "False" または "NotImplemented" を返さな
      ければなりません。"True" を返す場合は、*subclass* はこの ABC の
      サブクラスと見なされます。"False" を返す場合は、*subclass* はた
      とえ通常の意味でサブクラスであっても ABC のサブクラスではないと
      見なされます。"NotImplemented" の場合、サブクラスチェックは通常
      のメカニズムに戻ります。

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

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

      class MyIterable:
          __metaclass__ = ABCMeta

          @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.abstractmethod(function)

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

   このデコレータを使うにはクラスのメタクラスが "ABCMeta" であるかまた
   は派生したものであることが求められます。 "ABCMeta" から派生したメタ
   クラスを持つクラスは全ての抽象メソッドおよびプロパティをオーバーラ
   イドしない限りインスタンス化できません。抽象メソッドは普通の
   'super' 呼び出し機構を使って呼び出すことができます。

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

   使い方:

      class C:
          __metaclass__ = ABCMeta
          @abstractmethod
          def my_abstract_method(self, ...):
              ...

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

abc.abstractproperty([fget[, fset[, fdel[, doc]]]])

   組み込みの "property()" のサブクラスで、抽象プロパティであることを
   示します。

   この関数を使うにはクラスのメタクラスが "ABCMeta" であるかまたは派生
   したものであることが求められます。 "ABCMeta" から派生したメタクラス
   を持つクラスは全ての抽象メソッドおよびプロパティをオーバーライドし
   ない限りインスタンス化できません。抽象プロパティは普通の 'super' 呼
   び出し機構を使って呼び出すことができます。

   使い方:

      class C:
          __metaclass__ = ABCMeta
          @abstractproperty
          def my_abstract_property(self):
              ...

   この例は読み取り専用のプロパティを定義しています。プロパティ定義の
   「長い」形式の宣言を使って、読み書き出来る抽象プロパティを定義する
   ことができます:

      class C:
          __metaclass__ = ABCMeta
          def getx(self): ...
          def setx(self, value): ...
          x = abstractproperty(getx, setx)

-[ 注記 ]-

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