2016-12-17 63 views
0

我想創建兩個A類和B類,其中B是A的一個輕微但顯着的變體,然後創建第三個類C,它可以繼承A或B並添加功能給他們。問題是,我如何告訴C根據我的偏好繼承A或B?Python - 選擇要繼承的類

爲了讓事情更加清楚,假設我有這樣的代碼:

class A: 

    def __init__(self, x, y): 
     self.x = x 
     self.y = y 

    def first(self): 
     return do_something(1) 

    def second(self): 
     return do_something(2) 

    def third(self): 
     return do_something(3) 

    def start(self): 
     self.first() 
     self.second() 
     self.third() 

class B(A): 

    def __init__(self, x, y, z): 
     super().__init__(x, y) 
     self.z = z 

    def second(self): 
     super().second() 
     do_stuff() 

    def third(self): 
     do_other_stuff() 

這是我使用的代碼的一個非常簡化的版本。特別地,A代表製造系統的模擬器,而B代表相同製造系統的模擬器,並修改主機牀的行爲。

現在,我想要的是添加代碼來計算一些統計數據。它的作用是這樣的:

class C(A): 

    def __init__(self, *args): 
     super().__init__(*args) 
     self.stat = 0 

    def second(self): 
     super().second() 
     self.stat += 1 

    def third(self): 
     super().third() 
     self.stat *= 3 

的問題是,C類作品完全相同的方式是否如果我繼承了A類(如前面的列表)或B類(完全相同的代碼,以作爲第一行class C(B):

我該怎麼做?或者我使用的是不可行的方法?我認爲一個理想的解決方案是能夠在初始化C時選擇繼承A或B的類。或者,也許,能夠傳遞給C類繼承的類。

我做了一些研究,並且我發現了聚合的可能性(我不知道befo重新),但我沒有看到它真的有用。作爲最後一點,請注意A類可能有多達20-30個方法,並且當我使用類CI時,希望類A(或B,取決於它繼承的內容)與之前的C中添加的塊完全一樣工作。

P.S.我正在尋找一個可能優雅,沒有代碼沉重,「pythonic」的方式來做到這一點。我也非常期待在你認爲可以做得更好的事情上提供建議。最後,我可以完全修改C類,但A類和B類必須保持(除了小的變化)相同。

+2

爲什麼你通過繼承來做到這一點?爲什麼不使用* composition *,使'C'成爲'A'或'B'中的一個封裝器,然後在運行時傳遞給你需要的任何一個?你能否給出一個你想要實現的東西的抽象例子? – jonrsharpe

+0

我會盡力解釋一下:我正在製作一個下一個事件模擬器,其中有N個AGV攜帶一部分由兩個機牀進行焊接。我有基本版本A(正如我所說,它可以有20-30個方法)和一個修改版本B,其中機牀1的行爲是不同的。我想要C做的是運行模擬器(A或B),但是當發生某些事件時(即當一個零件進入機牀1開始計時,並且當相同的零件退出機牀時,工具2停止計算時間,以獲得平均製造時間) –

+0

我無法在Python中勝任,但在純粹的OOP註釋中:您是否考慮過裝飾模式? https://en.m.wikipedia.org/wiki/Decorator_pattern – korolar

回答

1

您可以使用新款式及其方法分辨率訂單

考慮這些定義:

class A(object): 
    def __init__(self, x): 
     pass 

    def foo(self): 
     print "A" 

class B(object): 
    def __init__(self, x, y): 
     pass 

    def foo(self): 
     print "B" 

你可以建立旨在將功能添加到AB一個mixin:

class Cmix(object): 
    def foo(self): 
     super(Cmix, self).foo() 
     print "mix" 

和來自CmixA(或B,分別)繼承:

class CA(Cmix, A): 
    pass 

class CB(Cmix, B): 
    pass 

最後,您可以編寫一個方便的功能基礎上的參數個數CACB之間做出選擇:

def C(*args): 
    if len(args) == 1: 
     return CA(*args) 
    else: 
     return CB(*args) 

現在我們有

C(1).foo() 
# A 
# mix 
C(1, 2).foo() 
# B 
# mix 

注意C是不是一個真正的類和你例如,在isinstance中不能將其用作第二個參數。