On Fri, 14 Aug 2009 16:49:47 +0200, Jean-Michel Pichavant wrote: > Hi fellows, > > Does anyone know a way to write virtual methods (in one virtual class) > that will raise an exception only if called without being overridden ? > Currently in the virtual method I'm checking that the class of the > instance calling the method has defined that method as well.
I'm not entirely sure of the terminology -- is this the same as an abstract base class? Googling has not enlightened me. Given your example, it seems to be. > Example: > > class Stream(object): > """Interface of all stream objects""" > def resetStats(self): > """Reset the stream statistics. All values a zeroed except the > date.""" > _log.info('Reset statistics of %s' % self) > if self.__class__.resetStats == Stream.resetStats: > raise NotImplementedError() The usual idiom I've seen for abstract methods is to simplify the check, and to put it *before* any work is done: class Stream(object): """Interface of all stream objects""" def resetStats(self): if self.__class__ is Stream: raise NotImplementedError() _log.info('Reset statistics of %s' % self) Even simpler is to just put the check in __init__, so to prevent the caller from creating an instance of the class: class AbstractStream(object): def __init__(self): if self.__class__ is Stream: raise NotImplementedError('abstract class') def resetStats(self): # This does not need to be over-ridden. _log.info('Reset statistics of %s' % self) def whatever(self): # This *must* be over-ridden, and *cannot* be called raise NotImplementedError('abstract method') If you have a lot of methods, you can probably reduce the boilerplate with decorators: # Untested from functools import wraps def abstract(func): # Abstract methods don't have to be over-ridden, so long as they # are called from a subclass of the abstract class. @functools.wraps(func) def inner(self, *args, **kwargs): if self.__class__ is Stream: raise NotImplementedError() return func(self, *args, **kwargs) return inner def virtual(func): # Virtual methods must be over-ridden, and must not be called by # inheritance. @functools.wraps(func) def inner(self, *args, **kwargs): raise NotImplementedError() return inner class Stream(object): @abstract def __init__(self): pass def resetStats(self): _log.info('Reset statistics of %s' % self) @virtual def whatever(self): pass -- Steven -- http://mail.python.org/mailman/listinfo/python-list