Reputation: 3159
I implement abstract class with abc package. The program below shows no problems.
Is there any way to make it fail because abstract MyMethod
did have an argument a
but the implementation of 'MyMethod' in class Derivative
didn't? So I would like specify not only methods in the interface class Base
but also arguments of these methods.
import abc
#Abstract class
class Base(object):
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
def MyMethod(self, a):
'MyMethod prints a'
class Derivative(Base)
def MyMethod(self):
print 'MyMethod'
Upvotes: 8
Views: 7118
Reputation: 492
The code below is copied from a proxy-class, which works analogous. It checks that all methods are present and that the method signatures are identical. The work is done in _checkImplementation(). Note the two lines starting with ourf and theirf; _getMethodDeclaration() translates the signatures into strings. Here I chose to require both to be exactly identical:
@classmethod
def _isDelegatableIdentifier(cls, methodName):
return not (methodName.startswith('_') or methodName.startswith('proxy'))
@classmethod
def _getMethods(cls, aClass):
names = sorted(dir(aClass), key=str.lower)
attrs = [(n, getattr(aClass, n)) for n in names if cls._isDelegatableIdentifier(n)]
return dict((n, a) for n, a in attrs if inspect.ismethod(a))
@classmethod
def _getMethodDeclaration(cls, aMethod):
try:
name = aMethod.__name__
spec = inspect.getargspec(aMethod)
args = inspect.formatargspec(spec.args, spec.varargs, spec.keywords, spec.defaults)
return '%s%s' % (name, args)
except TypeError, e:
return '%s(cls, ...)' % (name)
@classmethod
def _checkImplementation(cls, aImplementation):
"""
the implementation must implement at least all methods of this proxy,
unless the methods is private ('_xxxx()') or it is marked as a proxy-method
('proxyXxxxxx()'); also check signature (must be identical).
@param aImplementation: implementing object
"""
missing = {}
ours = cls._getMethods(cls)
theirs = cls._getMethods(aImplementation)
for name, method in ours.iteritems():
if not (theirs.has_key(name)):
missing[name + "()"] = "not implemented"
continue
ourf = cls._getMethodDeclaration(method)
theirf = cls._getMethodDeclaration(theirs[name])
if not (ourf == theirf):
missing[name + "()"] = "method signature differs"
if not (len(missing) == 0):
raise Exception('incompatible Implementation-implementation %s: %s' % (aImplementation.__class__.__name__, missing))
Upvotes: 3