2016-12-09 5 views
2

私はいくつかのプロジェクトを構築する方法をアドバイスしたいと思います。Pythonでの合成継承

私はいくつかの方法で基本クラスを取得しました。

class Base(object): 
    def method1(self): 
    # some code 
    def method2(self): 
    # some code 
    def method3(self): 
    # some code 
... and some other methods 

私のプロジェクトでは、基本クラスを変更することはできません。プロジェクト要件を適用するには、そのクラスに固有のものでなければなりません。

有効にするかどうかの要件がいくつかあります。与えられた構成に依存します。私。私はmethod1()、method2()、method3()、またはそれらの任意の組み合わせをオーバーライドできるようにしたいと思います。

1つの代替案は、いくつかの継承クラスを構築することです。

class Child1(Base): 
    def method1(self): 
    # some code 

class Child2(Base): 
    def method2(self): 
    # some code 

class Child3(Base): 
    def method3(self): 
    # some code 

次に、複数の継承を使用してそれらの構成を適用することができます。しかし、このアプローチはすべての可能な組み合わせをカバーするためにはうまくいきません。(例えば、Child4()を使用するとどうなりますか?)

もう一つの方法は、単一の継承クラスを持ち、if句を使用して、スーパーメソッドまたは派生した動作を適用します。

class Child(Base): 
    def method1(self): 
    if not self.override1: 
     # call super 
    else: 
     # some code 

    def method2(self): 
    if not self.override2: 
     # call super 
    else: 
     # some code 

    def method3(self): 
    if not self.override3: 
     # call super 
    else: 
     # some code 

私はこの選択肢にもっと好意的ですが、これを行うためのより良いオブジェクト指向のアプローチが必要だと感じています。

ご意見やご提案はありますか?

どうもありがとう

PS:私は、2.7をPythonのように拘束しています、と私はコードを共有することを計画しているので、私はむしろ平均Pythonプログラマで理解しやすい(とだけでなく、高度であるソリューションを持っていますプログラマー)。

+0

質問は、おそらくあまりにも広いです。変更の程度によってインスタンスが変更されていないインスタンスと大きく異なる振る舞いをする場合 - それは別のものと見なすことができるほど、最後の解決策は間違っていると言えます。多重継承/混合アプローチ。 – wwii

答えて

2

私は、何のコードの重複を、それが管理しやすいと思われる最初の選択肢を好まない:

class A: 
    def one(self): 
     return 'one |' 
    def two(self): 
     return 'two |' 
    def three(self): 
     return 'three |' 
    def four(self): 
     return 'four |' 

class B(A): 
    def one(self): 
     return 'one foo |' 

class C(A): 
    def two(self): 
     return 'two foo |' 

class D(A): 
    def three(self): 
     return 'three foo |' 

class BC(B, C): 
    pass 
class CD(C, D): 
    pass 
class BD(B, D): 
    pass 

今、あなたの中から選択する7つのものを持っています。あなたは簡単にそれが実行時にあるものの種類を伝えることができ、必要に応じて:

>>> bc = BC() 
>>> isinstance(bc, A) 
True 
>>> isinstance(bc, CD) 
False 
>>> isinstance(bc, BC) 
True 

そして、あなたはおそらく見つけるでしょう、あなたは何かを忘れてしまったし、追加するのは簡単です:

#oops now I need this 
class X(A): 
    def four(self): 
     pass 
# and this $#%^!* 
class B1(A): 
    def one(self): 
     return 'one bar |' 
1

に入れたままにしてくださいクラス定義はコードを実行することに注意してください。あなたの子クラスのメソッドを条件付きで定義したり無視したりすることができます:

class Child(Base): 
    if something: 
     def method1(self, etc): 
      pass 

これは一例です。条件を設定すると、クラス定義の前に起こることがあることに注意してください - これは動的パラメータないです:

#!python3 
import sys 

special = False 

if "--special" in sys.argv: 
    special = True 


class Base: 
    def method1(self): 
     print("Base method1") 


    def method2(self): 
     print("Base method2") 

class Child(Base): 
    def method3(self): 
     print("Child method3") 

    if special: 
     def method1(self): 
      print("Child method1") 


ch = Child() 
ch.method1() 
ch.method2() 
ch.method3() 

出力は次のとおりです。

$ python test.py --special 
Child method1 
Base method2 
Child method3 

$ python test.py 
Base method1 
Base method2 
Child method3 
+0

ニース!つまり、私はsys.argvの条件にのみ基づいていますか?それとも別の選択肢がありますか? – yuval

+1

他の選択肢は間違いありません。私はそれがデモなので、argvの条件に基づいています。クラスを定義する前に値を確定することができれば、他の任意の条件に基づいて基にすることができます。そのことについては、クラス定義を関数の中に入れ、それを呼び出してクラスを返すことができます。 –