Dato che Python consente l'ereditarietà multipla, che aspetto ha l'ereditarietà idiomatica in Python?
In linguaggi con ereditarietà singola, come Java, l'ereditarietà verrebbe utilizzata quando si potrebbe dire che un oggetto "è-a" di un altro oggetto e si desidera condividere il codice tra gli oggetti (dall'oggetto padre all'oggetto figlio). Ad esempio, potresti dire che Dogè un Animal:
public class Animal {...}
public class Dog extends Animal {...}
Ma poiché Python supporta l'ereditarietà multipla, possiamo creare un oggetto componendo insieme molti altri oggetti. Considera l'esempio seguente:
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
È un uso accettabile o buono dell'ereditarietà multipla in Python? Invece di dire l'eredità è quando un oggetto "è-a" di un altro oggetto, creiamo un Usermodello composto da UserServicee LoggingService.
Tutta la logica per le operazioni di database o di rete può essere mantenuta separata dal Usermodello inserendoli UserServicenell'oggetto e mantenendo tutta la logica per l'accesso LoggingService.
Vedo alcuni problemi con questo approccio sono:
- Questo crea un oggetto Dio? Dal momento che
Usereredita o è composto da,UserServiceeLoggingServicesta davvero seguendo il principio della singola responsabilità? - Per accedere ai metodi su un oggetto parent / next-in-line (ad esempio,
UserService.validate_credentialsdobbiamo usaresuper. Questo rende un po 'più difficile vedere quale oggetto gestirà questo metodo e non è chiaro come, diciamo , istanziandoUserServicee facendo qualcosa di simileself.user_service.validate_credentials
Quale sarebbe il modo Pythonic per implementare il codice sopra?