How to enforce method signature for child classes?

后端 未结 5 1657
隐瞒了意图╮
隐瞒了意图╮ 2021-01-06 17:05

Languages like C#, Java has method overloads, which means if child class does not implement the method with exact signature will not overwrite the parent method.

How

5条回答
  •  花落未央
    2021-01-06 17:59

    Update of the accepted answer to work with python 3.5.

    import inspect
    from types import FunctionType
    
    class BadSignatureException(Exception):
        pass
    
    
    class SignatureCheckerMeta(type):
        def __new__(cls, name, baseClasses, d):
            #For each method in d, check to see if any base class already
            #defined a method with that name. If so, make sure the
            #signatures are the same.
            for methodName in d:
                f = d[methodName]
    
                if not isinstance(f, FunctionType):
                    continue
                for baseClass in baseClasses:
                    try:
                        fBase = getattr(baseClass, methodName)
                        if not inspect.getargspec(f) == inspect.getargspec(fBase):
                            raise BadSignatureException(str(methodName))
                    except AttributeError:
                        #This method was not defined in this base class,
                        #So just go to the next base class.
                        continue
    
            return type(name, baseClasses, d)
    
    
    def main():
        class A(object):
            def foo(self, x):
                pass
    
        try:
            class B(A, metaclass=SignatureCheckerMeta):
                def foo(self):
                    """This override shouldn't work because the signature is wrong"""
                    pass
        except BadSignatureException:
            print("Class B can't be constructed because of a bad method signature")
            print("This is as it should be :)")
    
        try:
            class C(A):
                __metaclass__ = SignatureCheckerMeta
                def foo(self, x):
                    """This is ok because the signature matches A.foo"""
                    pass
        except BadSignatureException:
            print("Class C couldn't be constructed. Something went wrong")
    
    
    if __name__ == "__main__":
        main()
    

提交回复
热议问题