2016-12-09 84 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()或它們的任意組合。

一種替代方法是構造幾個繼承類。

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:我不得不Python 2.7版,因爲我打算共享的代碼,我寧願有一個解決方案,易於平均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 

現在你有七件事選擇。如果需要的話可以告訴你這是在運行時是什麼樣的事情:

>>> 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的條件,因爲它是一個演示。你可以根據你想要的任何其他條件,只要你可以在定義該類之前完成該值。對於這個問題,你可以把類定義放入一個函數中,然後調用它返回類。 –