Il problema qui è che sei stato indotto in errore nell'esprimere questo tipo di relazioni con l'ereditarietà. Non hai fatto nulla di sbagliato, questo problema caratterizza i problemi con l'ereditarietà e perché generalmente non è favorevole alla composizione.
Favor composition to inheritance
Ci sono molti approcci a questo problema, ma quello che segue è il più semplice:
Per prima cosa, hai una classe User, a differenza della tua gerarchia, questo rappresenta un utente di sistema, e questo è tutto.
Ovviamente, questi sono layout veloci, sostituiscono le proprietà con getter, setter, ecc.
interface HasSessionId
{
ID;
}
interface CanCheckPermission
{
HasPermissionTo(permission);
}
class AnnoUser implements CanCheckPermission, HasSessionId
{
ID;
}
class RegisterUser implements CanCheckPermission, HasSessionId
{
ID;
UserName;
FirstName;
LastName;
Login; //Sometimes it is helpful to separate the login into a a different concept to make impersonation easier, ect, you may or may not need this in your system.
}
Successivamente, hai i ruoli di sistema. Questa è una cosa completamente diversa da un utente. Qualsiasi comportamento o proprietà comuni che possono avere sono in un'interfaccia. Le interfacce implementano solo funzionalità minime e non dovrebbero essere viste come una classe base senza implementazione. Esprimono solo qualcosa che il sistema può fare.
interface IsAUser
{
User;
}
interface CanBuy
{
Buy(product);
}
I nostri singoli roll di sistema ora possono implementare queste interfacce per esprimere le loro funzioni disponibili, e sono libere di fare le cose diversamente se vogliono, ma possono avere un comportamento comune che vogliamo sfruttare, che è dove entra in gioco l'utilità di acquisto.
class BuyingUtility
{
//static stuff is generally bad, but this is the closest Java has to functions. Avoid static fields as much as possible
static Buy(product, IsAUser) { /*buy logic*/ }
}
class Admin implements IsAUser, CanBuy, CanSell
{
User;
Buy(product)
{
BuyingUtility.Buy(product, this);
}
}
class BuyerManager implements IsAUser, CanBuy
{
User;
Buy(product)
{
BuyingUtility.Buy(product, this);
}
}