I did a bit more messing about this evening with the interface class idea. I think the below implementation is fairly complete. It handles multiple inheritance cases where the interface gets satisfied by one of the parent classes.
def interfaceTypeFactory( metaclassSuper=type ): ''' returns an "Interface" metaclass. Interface classes work as you'd expect. Every method implemented on the interface class must be implemented on subclasses otherwise a TypeError will be raised at class creation time. usage: class IFoo( metaclass=interfaceTypeFactory() ): def bar( self ): pass subclasses must implement the bar method NOTE: the metaclass that is returned inherits from the metaclassSuper arg, which defaults to type. So if you want to mix together metaclasses, you can inherit from a subclass of type. For example: class IFoo( metaclass=interfaceTypeFactory( trackableTypeFactory() ) ): def bar( self ): pass class Foo(IFoo): def bar( self ): return None print( IFoo.GetSubclasses() ) ''' class _AbstractType(metaclassSuper): _METHODS_TO_IMPLEMENT = None _INTERFACE_CLASS = None def _(): pass _FUNC_TYPE = type( _ ) def __new__( cls, name, bases, attrs ): newCls = metaclassSuper.__new__( cls, name, bases, attrs ) #if this hasn't been defined, then cls must be the interface class if cls._METHODS_TO_IMPLEMENT is None: cls._METHODS_TO_IMPLEMENT = methodsToImplement =  cls._INTERFACE_CLASS = newCls for name, obj in attrs.items(): if type( obj ) is cls._FUNC_TYPE: methodsToImplement.append( name ) #otherwise it is a subclass that should be implementing the interface else: if cls._INTERFACE_CLASS in bases: for methodName in cls._METHODS_TO_IMPLEMENT: #if the newCls' methodName attribute is the same method as the interface #method, then the method hasn't been implemented. Its done this way because #the newCls may be inheriting from multiple classes, one of which satisfies #the interface - so we can't just look up the methodName in the attrs dict if getattr( newCls, methodName, None ).im_func is getattr( cls._INTERFACE_CLASS, methodName ).im_func: raise TypeError( "The class %s doesn't implement the required method %s!" % (name, methodName) ) return newCls return _AbstractType class ITest( metaclass=interfaceTypeFactory() ): def something( self ): pass def otherthing( self ): pass class Test_implementsAll(ITest): def something( self ): pass def otherthing( self ): pass class Test_subclassImplementsAll(Test_implementsAll): pass class SimilarInterface(object): def something( self ): pass def otherthing( self ): pass class MultipleInheritanceTest(SimilarInterface, ITest): pass #will throw TypeError class Test_implementsSome(ITest): def something( self ): pass #will throw TypeError class Test_implementsNone(ITest): pass
There are some simple tests at the bottom that demonstrate the idea.
As you can see, the class MultipleInheritanceTest has no methods, but its parent class SimilarInterface does implement the required methods, so the class passes without issue.
Anyway – I figured after the previous post I should at least finish the thought. The implementation in the last post wasn’t complete.
This post is public domain
This entry was posted on Thursday, May 19th, 2011 at 21:16 and is filed under main. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.