3

What I want is to enforce that when a child class inherits from a parent and that it overrides the parent method without explicitly calling it, an error is raised. The errror could be raised at initialization of the bad class or when calling the method.

The goal is to make sure that users of the Mother class performed some actions present in the mother method.

Example

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

upon calling:

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

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

Is this really possible ? Any answer or workaround tricks is welcomed.

Oily
  • 538
  • 3
  • 11

1 Answers1

3

Yeah, it's definitely possible, at least during runtime. U can create a Metaclass that modifies how classes are created, the idea is to change the necessary_method signature by adding a mother_method_called flag that is only going to be true when the Mother version is called, otherwise it's going to raise a Value Error. For example in 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
marcos
  • 4,473
  • 1
  • 10
  • 24