Avoid multiple inheritance

This is classical Composition over Inheritance 1 2.

However, the examples demonstrating it are usually straightforward, often even the difference between the has-a and is-a relationship is logical. This doesn't have to be the case in real code and more over, while some languages technicaly support multiple inheritance, it is utterly broken.

Lets first take a look at C++ where multiple inheritance is viable.

class Parent1 {
    public:
    int x;
    Parent1(int x) : x(x) {}
};

class Parent2 {
    public:
    int x;
    Parent2(int x): x(x) {}
};

class Child : public Parent1, Parent2 {
    public:
    Child(int x, int y) : Parent1(x), Parent2(y) {}

    void print() {
        cout << "Parent1: " << Parent1::x << endl;
        cout << "Parent2: " << Parent2::x << endl;
    }
};

int main(void) {
    Child c(1, 2);
    c.print();
}

We corectly get Parent1: 1 and Parent2: 2. This is because each instance has private fields namespace for each class.

On the other hand, in dynamicly typed languages 3 like python, the equivalent code is utterly broken.

class Parent1:
    def __init__(self, x):
        self.x = x

    def get_x(self):
        return self.x

class Parent2:
    def __init__(self, x):
        self.x = x

    def get_x(self):
        return self.x

class Child(Parent1, Parent2):
    def __init__(self, x, y):
        Parent1.__init__(self, x)
        Parent2.__init__(self, y)

    def print(self):
        print("Parent1: " + str(Parent1.get_x(self)))
        print("Parent2: " + str(Parent2.get_x(self)))

Child(1, 2).print()

Here we get 2 for both parents. Using multiple inheritance in python means each parent needs to intimately know the implementation details of every other parent not to step over each other. This is bound to eventually cause strange bugs. One could argue to use private members via the double underscore prefix but eww.

1

http://wiki.c2.com/?CompositionInsteadOfInheritance

2

https://en.wikipedia.org/wiki/Composition_over_inheritance

3

FIXME: not sure if dynamic typing alone implies shared this/self

4

FIXME: use more realistic class names.