Amaranth
Amaranth

Reputation: 53

Repeating Code vs. Multiple Inheritance

I have been cleaning up code that handles save data for Contacts and Clients. My goal has been to overhaul my code in order to maximize maintainability, since my project has undergone some severe code rot. In doing so, I have encountered a dilemma in inheritance structure.

class SaveFile is my base class for anything that gets saved onto the hard drive.

class GeneralContact(SaveFile) is a base class for any kind of contact.

class PersonalContact(GeneralContact) keeps track of data for personal contacts, while class CorporateContact(GeneralContact) keeps track of data for corporate contacts.

My difficulty lies in how to structure for clients. There are two types of clients: personal and corporate.

I could do class PersonalClient(PersonalContact) and class CorporateClient(CorporateContact). However, both the personal and corporate clients would use essentially the same methods and attributes, so I would be repeating code.

I could also do class GeneralClient, and then class PersonalClient(PersonalContact, GeneralClient) and class CorporateClient(CorporateContact, GeneralClient), which would only require me to implement the client code once, and then override the __str__ methods for both.

So my question is, is there a preferable/more pythonic choice between using single inheritance and repeating code, or using multiple inheritance and digging into those complexities?

Upvotes: 2

Views: 151

Answers (1)

Raymond Hettinger
Raymond Hettinger

Reputation: 226396

So my question is, is there a preferable/more pythonic choice between using single inheritance and repeating code, or using multiple inheritance and digging into those complexities?

The situation you described is what multiple inheritance was designed for. There are two separate blocks of reusable code. Multiple inheritance let's you use both.

Whether you encounter "complexities" or not depends on the situation:

  • If there are no overlapping method names between the two parent classes, then multiple inheritance tends to be as simple as single inheritance.

    class A:
        def p(self):
            pass
    
    class B:
        def q(self):
            pass
    
    class C(A, B):
        'Both A.p() and B.q() are inherited'
    
  • If there is an overlap, but only one method should run, it is also simple. Just order the classes so that the one with the dominant overriding methods goes first.

    class A:
        def p(self):
            pass
    
    class B:
        def p(self):
            pass
    
    class C(A, B):
        'Only A.p() is used'
    
  • If there is an overlap and both parent methods need to run, the simplest solution is to have the child method call both parent methods.

    class A:
        def p(self):
            pass
    class B:
        def p(self):
            pass
    
    class C(A, B):
        'Both A.p() and B.p() are called'
    
        def p(self):
            A.p(self)
            B.p(self) 
    
  • Really, the only complex cases are when you want to design cooperative classes that can be freely mixed and that are fully decoupled from one another. The techniques for achieving that goal are discussed in "Python's super() considered super".

Upvotes: 3

Related Questions