jeudi 19 décembre 2019

Using abstract class with overridden constructor in Python

I am attempting to use the template method pattern with abc in Python to create an extendible base class. Primarily, I need the constructor of one of the derived classes to implement a hook method that is called from the base's constructor. This is what I have in the base class:

import abc

class MyBase(abc.ABC):
    @abc.abstractmethod
    def __init__(self, attr1, attr2):
        # this is only implemented in one child class
        MyBase.validate_attrs(attr1, attr2)
        self.attr1 = attr1
        self.attr2 = attr2

    @staticmethod
    @abc.abstractmethod
    def validate_attrs(attr1, attr2):
        """ In Child1, raise exception if attr1 or attr2 are invalid """
        pass

My code for the first child class looks like this:

class ChildOne(MyBase):
    def __init__(self, attr1, attr2, attr3):
        # this class will implement validate_attrs, and logic needs to be called here
        super().__init__(attr1, attr2)
        self.attr3 = attr3

    # Override default from MyBase
    @staticmethod
    def validate_attrs(attr1, attr2):
        if attr1 < attr2:
            raise ValueError("attr1 is too small!")  # this is just stand in logic to keep it brief

However, when I instantiate ChildOne, the default pass is what is used. I suppose this is to be expected, as I specifically call MyBase.validate_attrs. I tried using a class method, but I get the same result. Logically, it seems like I am trying to call the child class's logic from the parent class, which obviously goes against everything anybody's ever learned in OO class. How can I use the template method pattern to achieve this functionality using a hook method in the parent class so that super() runs the implemented version in the child class?

Aucun commentaire:

Enregistrer un commentaire