2010-05-13 54 views
1

我已經有一些回調和自己的接口,像一類:壓倒一切的回調避免污染屬性

class Service: 
    def __init__(self): 
     connect("service_resolved", self.service_resolved) 

    def service_resolved(self, a,b c): 
     ''' This function is called when it's triggered 
      service resolved signal and has a lot of parameters''' 

的連接功能例如gtkwidget.connect,但我想,這個連接是東西比較一般,所以我決定用一種「扭曲的像」的方法:

class MyService(Service): 

    def my_on_service_resolved(self, little_param): 
      ''' it's a decorated version of srvice_resolved ''' 
    def service_resolved(self,a,b,c): 
     super(MyService,self).service_resolved(a,b,c) 
     little_param = "something that's obtained from a,b,c" 
     self.my_on_service_resolved(little_param) 

所以我可以通過重寫my_on_service_resolved使用的MyService。

問題是「屬性」污染。在實際的實現中,Service有一些屬性可能會在MyService和子類MyService中被意外覆蓋。

如何避免屬性污染?

我也想過是一個「包裝」之類的做法,但我不知道這是否是一個很好的解決方案:

class WrapperService(): 
    def __init__(self): 
     self._service = service_resolved 
     # how to override self._service.service_resolved callback? 
    def my_on_service_resolved(self,param): 
     ''' 
     ''' 

回答

3

避免意外衝突與派生類的原因是「雙leading-下劃線「的命名方法存在:如果您在類Service__foo中命名屬性,則Python編譯器將在內部」mangle「,名稱爲_Service__foo,這意味着不太可能發生意外衝突。唉,不是不可能的:一個子類可能被命名爲Service(並住在另一個模塊)和有它自己的__foo屬性...這將被命名 - 完全相同的方式,導致再次衝突。改進包括命名基類BaseService等,利用派生類不太可能被命名爲Base的事實。但是,最後,除了清楚地記錄像這樣的約定之外別無選擇(至少如果子類將由具有很少Python經驗的程序員編寫)。

我不認爲「意外衝突」問題足以迫使您完全放棄子類化(有利於僅使用包裝),這基本上是避免意外名稱衝突某些的唯一方法。你稱之爲「類似扭曲」的方法(實際上是模板方法設計模式的一個例子)是非常可行的,並且在現實生活實踐中,命名和設計選擇文檔的組合方式證明足以避免其「衝突」風險。