Given that Python allows for multiple inheritance, what does idiomatic inheritance in Python look like?
In languages with single inheritance, like Java, inheritance would be used when you could say that one object "is-a" of an another object and you want to share code between the objects (from the parent object to the child object). For example, you could say that Dog
is a Animal
:
public class Animal {...}
public class Dog extends Animal {...}
But since Python supports multiple inheritance we can create an object by composing many other objects together. Consider the example below:
class UserService(object):
def validate_credentials(self, username, password):
# validate the user credentials are correct
pass
class LoggingService(object):
def log_error(self, error):
# log an error
pass
class User(UserService, LoggingService):
def __init__(self, username, password):
self.username = username
self.password = password
def authenticate(self):
if not super().validate_credentials(self.username, self.password):
super().log_error('Invalid credentials supplied')
return False
return True
Is this an acceptable or good use of multiple inheritance in Python? Instead of saying inheritance is when one object "is-a" of another object, we create a User
model composed of UserService
and LoggingService
.
All the logic for database or network operations can be kept separate from the User
model by putting them in the UserService
object and keep all the logic for logging in the LoggingService
.
I see some problems with this approach are:
- Does this create a God object? Since
User
inherits from, or is composed of,UserService
andLoggingService
is it really following the principle of single responsibility? - In order to access methods on a parent/next-in-line object (e.g.,
UserService.validate_credentials
we have to usesuper
. This makes it a little bit more difficult to see which object is going to handle this method and isn't as clear as, say, instantiatingUserService
and doing something likeself.user_service.validate_credentials
What would be the Pythonic way to implement the above code?