【问题标题】:How to enforce mandatory parent method call when calling child method?调用子方法时如何强制执行父方法调用?
【发布时间】:2021-06-09 08:45:09
【问题描述】:

我想要强制当子类从父类继承并且它覆盖父方法而不显式调用它时,会引发错误。 该错误可能在初始化错误类或调用方法时引发。

目标是确保 Mother 类的用户执行了一些体现在 Mother 方法中的操作。

例子

class Mother():
    def necessary_method(self):
         # do some necessary stuff

class GoodChild(Mother):
    def necessary_method(self):
        # necessary parent call
        super().necessary_method()

class BadChild(Mother):
    def necessary_method(self):
         # no parent call
         return

调用时:

good = GoodChild()
# works fine
bad = BadChild()
# exception could be raised here

good.necessary_method()
# works fine
bad.necessary_method()
# exception could be raised here

这真的可能吗? 欢迎任何答案或解决方法。

【问题讨论】:

    标签: python inheritance methods overriding


    【解决方案1】:

    是的,这绝对是可能的,至少在运行时是这样。你可以创建一个Metaclass 来修改类的创建方式,这个想法是通过添加一个mother_method_called 标志来更改necessary_method 签名,该标志只有在调用Mother 版本时才会为真,否则它会继续提出Value Error。比如python3:

    class MotherMetaClass(type):
        def __new__(cls, name, bases, attrs):
            method_name = 'necessary_method'
            mother_class_name = 'Mother'
            original_necessary_method = attrs.get(method_name)
    
            def necessary_method_validated(*args, **kwargs):
                original_necessary_method(*args, **kwargs)
    
                if name == mother_class_name:
                    cls.mother_method_called = True
                else:
                    if not cls.mother_method_called:
                        raise ValueError(f'Must call "super()" when overriding "{method_name}".')
                    cls.mother_method_called = False
    
            attrs[method_name] = necessary_method_validated
    
            return super().__new__(cls, name, bases, attrs)
    
    
    class Mother(metaclass=MotherMetaClass):
        def necessary_method(self):
            print('Parent method called.')
    
    
    class GoodChild(Mother):
        def necessary_method(self):
            super().necessary_method()
            print('Good child method called.')
    
    
    class BadChild(Mother):
        def necessary_method(self):
            print("Bad child method called.")
    
    
    a = GoodChild()
    a.necessary_method()  # it's going to work properly
    
    
    b = BadChild()
    b.necessary_method()  # it's going to raise Value Error
    

    【讨论】:

    • 不错的答案,但有一个小问题是包装器没有保留返回值。易于修复。
    • 对,只要把它存储在一个变量中,最后返回它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多