1

I have a class design where the Children classes inheriting from a certain Parent class just differ in some parameters, but the Parent class contains all methods, which are using the parameters provided as class variables on the Children. So, in other words, each of my Child classes is fully described by the list of parameters and the inheritance of the Parent class.

So, let's say, I have the following classes:

class Parent():
    def __init__(self, **kwargs):
        for param in self.__class__.parameters:
            self.setattr(param, kwargs.get(param))

    def compare(self, other):
        for param in self.__class__.parameters:
            if self.getattr(param) != other.getattr(param):
                return False
        return True

class ChildA(Parent):
    parameters = ["length", "height", "width"]
    def __init__(self, **kwargs):
        super().__init__(**kwargs)


class ChildB(Parent):
    parameters = ["color", "taste"]
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

My actual classes are a bit different - I have more and more complex methods on the Parent class and also different kinds of parameters - , but this is sort of a minimum example of the design principle.

Since Parent class is relying on its Children to have the class variable parameters, I thought, I might want to enforce the existence of the class variable on each Child class. I have read that I achieve this by using a metaclass. But I have also read that most developers do not need to use metaclasses, and if in doubt, you probably don't need them. I have never worked with metaclasses before, and so I am in doubt whether I should use them, and so by that rule mentioned, I probably do not need a metaclass. But on the other hand, the term "metaclass" just sounds like a good match to my structure, since Parent really looks like something which could well be called "metaclass" in some sense (technically, not in terms of the way the terminus technicus metaclass is used in OOP, but in terms of: it is fully describing the behaviour of the children classes).

So, I wonder: Is there a different (better) design of classes to reflect my structure? Should I use a metaclass to enforce the existence of the parameters, or is there a better way to do so? Or should I just resign to enforce the existence of the parameters class variable on the Children classes in the first place?

2
  • Why would you not define interfaces (or for that matter actual method implementations) in the parent class that deal with the parameters visible to the parent and override them in the child class dealing with additional parameters in the child class? Commented Mar 24, 2019 at 5:24
  • @Sharad: In my situation, I have a bunch of methods and a bunch of Child classes. I would like to avoid the need to implement the methods on each Child class. The idea of that design is to avoid repetitive code on each Child class. But I am not sure, whether I fully understood what you mean. Could you make an example? That would help me clearly understanding you, I guess. Commented Mar 24, 2019 at 9:44

1 Answer 1

1

If using python3.6 or above, you can accomplish this using __init_subclass__ which I personally reason better with than a metaclass.

An example of __init_subclass__ based on the usecase described:

class Parent:
    def __init_subclass__(cls):
        if not hasattr(cls, 'parameters'):
          raise TypeError(f'Subclass of {cls} does not have a parameters class attribute')

    def __init__(self, **kwargs):
        for param in self.__class__.parameters:
            self.setattr(param, kwargs.get(param))

    def compare(self, other):
        for param in self.__class__.parameters:
            if self.getattr(param) != other.getattr(param):
                return False
        return True


class GoodChild(Parent):
    parameters = ['length', 'height', 'width']


class BadChild(Parent):
    pass

Which results in raising a TypeError exception when the BadChild class is created (not when it is instantiated):

TypeError: Subclass of <class '__main__.BadChild'> does not have a parameters class attribute
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.