2017-05-30 15 views
2

Javaでは、抽象クラスにすることでクラスのインスタンス化を防ぐことができます。私はPythonが同じように動作すると思った。しかし、私の驚きに、私は抽象クラスのオブジェクトを作成することが分かっ:抽象クラスのインスタンス化を防止する

from abc import ABCMeta 
class Foo(metaclass=ABCMeta): 
    pass 
Foo() 

はなぜPythonはこれを許可しないとどのように私はこれを防ぐことができますか?

+2

おそらく、抽象クラスにはいくつかの '@ abstractmethod'もあります。もしそうであれば、インスタンス化ができなくなります。現実には、ほとんど問題ではないはずです。 – deceze

+0

Pythonは面白いです。抽象メソッドはそれらの中にコードを持つことができ、スーパーも使用して呼び出すことができます。さて、 '抽象的な'であるために)# – codingsplash

+1

これはPythonの抽象的な概念です。:P – deceze

答えて

0

Pythonは「大人に同意する」ためのものです。必要に応じてプロジェクト内の命名規則(またはそのモジュールのメンバーシップ)によって、クラスを抽象としてマークできます。しかし、難解な「インスタンス化不可能な」抽象クラスを実行することは実現可能ですが、それはプロジェクトのセキュリティや優良性を高めるものではありません。

ので、ABCの抽象クラスの残りの機械を維持するために、あなたはABCMetaクラスを継承し、それがインスタンス化しないように__new__方法を飾るためにそれを使用することができます - ちょうど同じことを、そうでない場合は、代わりにtypeから継承します。

つまり、コードでは__new__というメタドをメタクラスとして作成したクラスにラップしています。そのメソッドが実行されると、インスタンス化しているクラスがABCメタ自体でマークされたクラスであるかどうかがチェックされます。そうであれば、代わりにタイプエラーが発生します。

class ReallyAbstract(ABCMeta): 
    def __new__(metacls, name, bases, namespace): 
     outter_cls = super().__new__(metacls, name, bases, namespace) 
     for bases in outter_cls.__mro__: 
      if getattr(getattr(bases, "__new__", None), "_abstract", False): 
       # Base class already marked as abstract. No need to do anything else 
       return outter_cls 
     original_new = getattr(outter_cls, "__new__") 
     if getattr(original_new, "_abstract", False): 
      # If we get a method that has already been wrapped 
      # just return it unchanged. 
      # TODO: if further classes on the hierarhy redfine __new__ 
      return outter_cls 

     def __new__(cls, *args, **kw): 
      if cls is outter_cls: 
       raise TypeError 
      return original_new(cls, *args, **kw) 
     __new__._abstract = True 
     outter_cls.__new__ = __new__ 
     return outter_cls 

、コンソール上に

In [7]: class A(metaclass=ReallyAbstract): 
    ...:  pass 
    ...: 

In [7]: A() 
    TypeError         Traceback (most recent call last) 
<ipython-input-7-...> in <module>() 
----> 1 A() 

.... 

ただ、完全を期すために - 彼らは、少なくとも1つの「abstractmethod」を含む場合はPythonでABCMetaさんがインスタンス化されていません。他のO.O.より静的な言語で強化された機能は、習慣によってこれを持つことです。しかし、はい、私は、AbstractClassのメカニズムを作成する作業に慣れて以来、おそらくあまり驚くべきことではないはずです。つまり、デフォルトでインスタンス化できないようにすべきです。

関連する問題