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 User
modello composto da UserService
e LoggingService
.
Tutta la logica per le operazioni di database o di rete può essere mantenuta separata dal User
modello inserendoli UserService
nell'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
User
eredita o è composto da,UserService
eLoggingService
sta davvero seguendo il principio della singola responsabilità? - Per accedere ai metodi su un oggetto parent / next-in-line (ad esempio,
UserService.validate_credentials
dobbiamo usaresuper
. Questo rende un po 'più difficile vedere quale oggetto gestirà questo metodo e non è chiaro come, diciamo , istanziandoUserService
e facendo qualcosa di simileself.user_service.validate_credentials
Quale sarebbe il modo Pythonic per implementare il codice sopra?