2012-11-29 54 views
-1

在這裏,我繼承了一個wxPython類並定義了一個名爲singleton的類方法。如何實現子類單例?

class AddressCellAttr(wx.grid.GridCellAttr): 
    _instance = None 

    def __init__(self): 
     wx.grid.GridCellAttr.__init__(self) 

     self.SetTextColour('#0000FF') 

    @classmethod 
    def singleton(cls): 
     if cls._instance == None: 
      cls._instance = cls() 

     return cls._instance 

class ValidAddressCellAttr(AddressCellAttr): 
    def __init__(self): 
     AddressCellAttr.__init__(self) 

     self.SetTextColour('#00FF00') 

class CorrectedAddressCellAttr(AddressCellAttr): 
    def __init__(self): 
     AddressCellAttr.__init__(self) 

     self.SetTextColour('#FFFF00') 

class InvalidAddressCellAttr(AddressCellAttr): 
    def __init__(self): 
     AddressCellAttr.__init__(self) 

     self.SetTextColour('#FF0000') 

class UnparsableAddressCellAttr(AddressCellAttr): 
    def __init__(self): 
     AddressCellAttr.__init__(self) 

     self.SetTextColour('#555555') 

其餘的類是第一個子類的子類。我認爲singleton類方法對所有的子類都有效,因爲它在類上運行,而子類實際上是一個單獨的類。

發生什麼事情是,我在AddressCellAttr上調用singleton一次後,單例方法也會在所有子類上返回同一個對象。爲什麼會發生?

+0

-1對公然和無償虐待單身人士,並試圖讓我們幫助你造成這個世界上的怪物。 – cHao

+0

@cHao:請閱讀我在sr2222的回答中寫下的最新評論,除非您能向我解釋解決問題的更好方法,而不是使用單身問題,否則請刪除否定的投票。 – Hubro

回答

0

不知道爲什麼你認爲你在這裏需要單例模式,但無論如何,你應該真的在__new__這樣做。

class Singleton(object): 

    def __new__(cls): 

     try: 
      return cls._instance 
     except AttributeError: 
      cls._instance = object.__new__(cls) 
      return cls._instance 

只要確保所有子類調用父__new__(),並記住,__new__()__init__()簽名必須匹配。

+0

我正在使用單例模式,因爲這些類都不需要多次實例化。爲什麼有人會使用單身模式? – Hubro

+0

@Codemonkey:使用單例模式的唯一有效理由是如果類*不能被多次實例化(例如,如果創建另一個實例會打開蟲洞或將機器設置爲火)。如果你只是不想*但只有一個實例,那麼就有一個更簡單的修復方法 - **不要*創建*但是隻有一個。**你將所有東西都設爲單例,現在你添加代碼來強制約束甚至不應該存在...更不用說,在整個地方硬編碼特定類的東西,使未來的變化成爲一場噩夢。 – cHao

+0

@cHao:這聽起來並不簡單。將類定義爲單例可能比在我的情況下維護單個實例容易得多。這些類在我的代碼中使用很多*,我需要更多的代碼來檢查全局實例,以便每次需要使用它們而不是將它們實現爲單例時。另外,我不能只在模塊的頂部實例化每個類的一個,因爲wxPython不允許我在'wx.App.OnInit'之後創建'wx.grid.GridCellAttr'對象(並且發生在不同的模塊) – Hubro

0

好吧,我在寫這個問題的時候自己想出了這一個。事實證明,當調用單例方法時,它確實接收了正確的子類作爲參數,但由於子類沒有在任何地方明確定義_instance,所以cls._instance將查找類鏈回到AddressCellAttr和原始_instance

的解決方案是特別限定_instance對於每個子類,像這樣:

class ValidAddressCellAttr(AddressCellAttr): 
    _instance = None 

    def __init__(self): 
     AddressCellAttr.__init__(self) 

     self.SetTextColour('#00FF00') 

等。