2016-07-30 40 views
0

假設我有以下類:如何「推廣」一個實例到一個子類?

class Plain(object): 
    def speak(self): 
     print 'ho-hum' 

class Fancy(Plain): 
    def exult(self): 
     print 'huzzah!' 

plain = Plain() 
plain.speak() 
# ho-hum 
plain.exult() 
# --------------------------------------------------------------------------- 
# AttributeError       Traceback (most recent call last) 
# <ipython-input-585-5f782c9ea88b> in <module>() 
# ----> 1 plain.exult() 
fancy = Fancy() 
fancy.speak() 
# ho-hum 
fancy.exult() 
# huzzah! 

...和假設,由於某種原因,我想以「推動」,使其成爲Fancy實例的Plain一個實例。

我知道我可以隨時修改實例的屬性__class__

plain.__class__ = Fancy 
plain.exult() 
# huzzah! 

...但我從不同的SO職位(例如,在這裏,這裏)聚集,這是不是一件好事做(至少不在生產代碼中)。

是否有更多的「生產代碼值得」的方式將實例提升爲子類?


FWIW,這使我對這個問題的實際使用情況如下。我正在與一個實現Web服務客戶端的第三方庫合作。這個客戶端可以做的事情是返回各種類的實例。這些類提供了很少的方法,而且它們提供的很少。我可以使用更多更強大的方法輕鬆地爲這些類編寫子類,但爲了使它們變得有用,我還需要爲那些當前返回API原始類的實例的API函數編寫包裝。總而言之,這個包裝器只需要將原始(「wrappee」)函數返回的實例提升爲我的增強子類的實例。

+1

[?如何轉換(繼承)父到子類(可能的重複http://stackoverflow.com/questions/10030412/how-to-convert-inherit -parent-to-child-class) – kwarunek

+1

你想要做的是[「狀態」設計模式](https://en.wikipedia.org/wiki/State_pattern)。應該有一個容器對象來照顧創建適當類的實例。不要試圖通過擺弄低級位來破解。 –

回答

3

你可以使用過程

fancy = Fancy(plain) 

和定義花式的構造函數,如果普通的實例給出的說法應該發生什麼。

class Plain: 
    def __init__(self, foo, bar): 
     self.foo = foo 
     self.bar = bar 
     self.status = 'plain' 

class Fancy: 
    def __init__(self, something): 
     if isinstance(something, Plain): 
       self.foo = something.foo 
       self.bar = something.bar 
     self.status = 'fancy' 
+0

對於OP的用例,我會使用包裝器(has-a)而不是子類(is-a)。但無論哪種方式,你都會像你已經說過的那樣使用Fancy的__init__。 –

相關問題