Dado que Python permite la herencia múltiple, ¿cómo es la herencia idiomática en Python?
En lenguajes con herencia única, como Java, la herencia se usaría cuando se pudiera decir que un objeto "es-a" de otro objeto y se desea compartir el código entre los objetos (desde el objeto primario hasta el objeto secundario). Por ejemplo, podría decir que Dog
es un Animal
:
public class Animal {...}
public class Dog extends Animal {...}
Pero dado que Python admite herencia múltiple, podemos crear un objeto componiendo muchos otros objetos juntos. Considere el siguiente ejemplo:
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
¿Es este un uso aceptable o bueno de la herencia múltiple en Python? En lugar de decir que la herencia es cuando un objeto "es-a" de otro objeto, creamos un User
modelo compuesto por UserService
y LoggingService
.
Toda la lógica para las operaciones de la base de datos o la red se puede mantener separada del User
modelo al colocarlas en el UserService
objeto y mantener toda la lógica para iniciar sesión en el LoggingService
.
Veo algunos problemas con este enfoque son:
- ¿Esto crea un objeto de Dios? ¿Ya que
User
hereda de, o está compuesto de,UserService
yLoggingService
realmente está siguiendo el principio de responsabilidad única? - Para acceder a los métodos en un objeto principal / siguiente en línea (por ejemplo,
UserService.validate_credentials
tenemos que usarlosuper
. Esto hace que sea un poco más difícil ver qué objeto va a manejar este método y no es tan claro como, por ejemplo, , instanciandoUserService
y haciendo algo comoself.user_service.validate_credentials
¿Cuál sería la forma Pythonic de implementar el código anterior?