metaclass conflictを解決する方法!!




takkun
どうも!たっくんです。
久々に体調不良でダウン、、、皆さんもお気をつけください!(`・ω・´)ゞ

ClassやMeta Classに慣れてきてアレコレやってみると、ぶつかるであろう壁に「metaclass conflict」があると思います(´・ω・`)

頭いたくなりそうな問題ですが、モジュールを使った対応方法をご紹介したいと思います!

metaclass conflictって?

Classツリーの中で、適用されたMeta Classが複数あり、そのMeta Classが継承関係にない場合に「metaclass conflict」が発生します!

ちょっと、コードを見てみましょう∠( ゚д゚)/

class MetaClassA(type):
    pass
         
class MetaClassB(type):
    pass
    
class ClassA(object):
    __metaclass__ = MetaClassA
    
class ClassB(object):
    __metaclass__ = MetaClassB
    
class ClassC(ClassA, ClassB):
    pass
    
obj = ClassC()

こちらのコードを図にすると、以下のようになります。

ClassC」のインスタンスを作ろうとすると、基底クラスの「ClassA」に適用した「MetaClassA」と、基底クラスの「ClassB」に適用した「MetaClassB」と競合してしまいエラーしてしまうのが「metaclass conflict」です。

Classと違って、Meta Classの方の継承ツリーはややっこしいですね(´;ω;`)

こんな時、どうするか!?

metaclass conflict」を修正するために、以下のモジュールを使ってクラスを修正したいと思います。ダウンロードしたファイルを「noconflict.py」にリネームして、読み込めるディレクトリに保存してください(`・ω・´)ゞ

直接記述していた「metaclass」に、モジュールの「classmaker()」を指定することで「metaclass conflict」の問題を解決します!

from noconflict import classmaker
 
class MetaClassA(type):
    pass
         
class MetaClassB(type):
    pass
    
class ClassA(object):
    __metaclass__ = MetaClassA
    
class ClassB(object):
    __metaclass__ = MetaClassB
    
class ClassC(ClassA, ClassB):
    __metaclass__ = classmaker()
    
obj = ClassC()