1

I am trying to wrap my head around multiple inheritance and contrived a very simple example that is not able to access all of the inherited attributes. This may or may not be possible, but if so I could use some help. Here is how my code is structured along with some comments.

I made a Status class with a single attribute (status). The idea is that all of the other classes can inherit from status and thus get the status attribute.

class Status():
    def __init__(self, status: str = ""):
        self.status = status

Now I will make a class 'A' which inherits from Status and adds some methods to connect or disconnect from something.

class A(Status):
    def __init__(self):
        super().__init__("Disconnected")

    def connect(self):
        if self.status == "Disconnected":
            print("Connecting A")
            self.status = "Connected"
        else:
            print("A already connected, doing nothing")

    def disconnect(self):
        if self.status == "Connected":
            print("Disconnecting A")
            self.status = "Disconnected"
        else:
            print("A already disconnected, doing nothing")

This seems to work. In my test code, I can instantiate an instanse of A, call the new methods as well ass access A's status.

    print('\n***Class A**')
    a = A()
    print(a.status)
    a.connect()
    print(a.status)

I then repeated this process and made a very simple class (B) which also inherits from Status. Following similar test code as before, I can instantiate an instance of B and access its status.

class B(Status):
    def __init__(self):
        super().__init__("B Uninitialized")

Now I would like to make a new class 'Composite' that inherits from A, B, and Status

class Composite(A, B, Status):
    def __init__(self):
        super(A, self).__init__()
        super(B, self).__init__()
        super(Status, self).__init__()
        self.status = "Composite Uninitialized"

This "works" as composite can read/write its status (inherited from Status) as well as call the methods inherited from A. However, I would also like to be able to access the status of the A and B objects in addition to composite's own status. It seems this should be doable, but I cannot figure out how. Thanks!!

Frac
  • 321
  • 5
  • 13
  • Since `A` and `B` already inherit from `Status`, you don't need to inherit from it in `Composite`. – Barmar Aug 17 '23 at 21:51
  • You don't need to call `super().__init__()` 3 times. Just call it once. As long as all the superclasses call `super().__init__()`, it will initialize all the parents automatically. – Barmar Aug 17 '23 at 21:53
  • 3
    `Composite` *is* `A` and *is* `B` and *is* `Status`. There is no separate `A`, etc. You've stumbled upon the [dreaded diamond pattern](https://en.wikipedia.org/wiki/Multiple_inheritance) which is very heavily discouraged. Consider favoring [composition over inheritance](https://stackoverflow.com/questions/20847727/python-inheritance-versus-composition) if you can - i.e. each class *has a* status, not *is a* status. – Woodford Aug 17 '23 at 21:53
  • In `Composite` your calls to `super` are **completely wrong**. There should only be *one* call, and the only way it should be called is `super(Composite, self)`, not any of the ones you actually made. – juanpa.arrivillaga Aug 17 '23 at 22:12
  • "However, I would also like to be able to access the status of the A and B objects in addition to composite's own status." **there are no `A` and `B` objects**, unless you mean the ones you crated earlier. "It seems this should be doable, " no, why should it be doable? It sounds like you think that a `Composite` instance should have access to the instance state of *other instances* merely because you are inheriting from their classes, but that isn't how inheritance works at all. – juanpa.arrivillaga Aug 17 '23 at 22:13
  • @Woodford the diamond pattern isn't a problem really. I agree composition should be favored (in general!) but you *can* make inheritance work here very easily. – juanpa.arrivillaga Aug 17 '23 at 22:15
  • 1
    note, in python, you *don't inherit instance attributes*. There is only **one `self.status`** attribute ever set on a `Composite` object (assuming you make the `super` calls correctly) – juanpa.arrivillaga Aug 17 '23 at 22:19
  • Thanks guys. These comments are pretty much in line with what I was finding elsewhere. The distinction between inheritance and composition is clear and understood. One issue I am having is with the super().__init__() If I change this section of code to ```class Composite(A, B, Status): def __init__(self): # super(A, self).__init__() # super(B, self).__init__() # super(Status, self).__init__() super().__init__() self.status = "Composite Uninitialized" ``` – Frac Aug 17 '23 at 22:59
  • then I get the following error: File "/home/elias/code/pyMultiInheritance/Modules.py", line 34, in __init__ super().__init__() File "/home/elias/code/pyMultiInheritance/Modules.py", line 8, in __init__ super().__init__("Disconnected") TypeError: B.__init__() takes 1 positional argument but 2 were given – Frac Aug 17 '23 at 23:00
  • @Frac because your `__init__` doesn't have the same signature. So either make them have the same signature, or use `*args,**kwargs` and extract what you need from each step. Watch this: https://www.youtube.com/watch?v=EiOglTERPEo – juanpa.arrivillaga Aug 18 '23 at 16:35
  • 1
    Also, *don't post this as a comment*. Edit your question and post it as formatted text – juanpa.arrivillaga Aug 18 '23 at 16:35

0 Answers0