views:

34

answers:

1

I've a class that has some callbacks and its own interface, something like:

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'''

the connect function is for example the gtkwidget.connect, but I want that this connection is something more general, so I've decided to use a "twisted like" approach:

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)

So I can use MyService by overriding my_on_service_resolved.

The problem is the "attributes" pollution. In the real implementation, Service has some attributes that can accidentally be overriden in MyService and those who subclass MyService.

How can I avoid attribute pollution?

What I've thought is a "wrapper" like approach but I don't know if it's a good solution:

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  A: 

Avoiding accidental clashes with derived classes is the reason the "double-leading-underscore" naming approach exists: if you name an attribute in class Service __foo, the Python compiler will internally "mangle" that name to _Service__foo, making accidental clashes unlikely. Alas, not impossible: a subclass might also be named Service (and live in another module) and also have its own __foo attribute... which would be named-mangled exactly the same way, resulting in a conflict again. Ameliorations include naming base classes BaseService and the like, exploiting the fact that a derived class is very unlikely to be named Basewhatever. But, in the end, there's no alternative to clearly documenting a convention such as this (at least if subclasses are going to be written by programmers with little Python experience).

I don't think the "accidental clash" issue is enough to force you to forego subclassing entirely (in favor of using wrapping exclusively), which is basically the only way to avoid accidental name clashes for certain. The approach you call "twisted-like" (and is actually a case of the Template Method design pattern) is quite viable, and a mix of convention for naming, and documentation of your design choices, in real-life practice proves sufficient to avoid its "clash" risks.

Alex Martelli