Domanda

Se hai diverse classi in cui desideri che ereditino da una classe base per funzionalità comuni, dovresti implementare la classe base usando una classe o una classe astratta?

È stato utile?

Soluzione

Dipende, se non vuoi mai essere in grado di creare un'istanza della classe base, rendila astratta. Altrimenti lascialo come una classe normale.

Altri suggerimenti

Se la classe base non deve essere istanziata, rendila una classe astratta - se la classe base deve essere istanziata, non renderla astratta.

In questo esempio ha senso rendere astratta la classe base poiché la classe base non ha alcun significato concreto:

abstract class WritingImplement
{
    public abstract void Write();
}

class Pencil : WritingImplement
{
    public override void Write() { }
}

Comunque in questo prossimo esempio puoi vedere come la classe base ha un significato concreto:

class Dog
{
    public virtual void Bark() { }
}

class GoldenRetriever : Dog
{
    public override void Bark() { }
}

È davvero tutto molto soggettivo - dovresti essere in grado di effettuare una buona valutazione in base alle esigenze del tuo dominio particolare.

Dipende, ha senso che la classe base in questione esista da sola senza essere derivata? Se la risposta è sì, allora dovrebbe essere una classe regolare, altrimenti dovrebbe essere una classe astratta.

Suggerisco:

  • Crea un'interfaccia.
  • Implementa l'interfaccia nella tua classe base.
  • Rendi la classe base una classe reale, non astratta (vedi sotto per il perché).

Il motivo per cui preferisco le classi reali invece delle classi astratte è che le classi astratte non possono essere istanziate, il che limita le opzioni future inutilmente . Ad esempio, in seguito potrei aver bisogno dello stato e dei metodi forniti dalla classe base ma non posso ereditare e non ho bisogno di implementare l'interfaccia; se la classe base è astratta, sono sfortunato, ma se la classe base è una classe normale, posso creare un'istanza della classe base e tenerla come componente dell'altra mia classe, e delegare all'istanza per riutilizzare il stato / metodi forniti.

Sì, ciò non accade spesso, ma il punto è: rendere astratto la classe base impedisce questo tipo di riutilizzo / soluzione, quando non c'è motivo per farlo.

Ora, se un'istanza della classe base sarebbe in qualche modo pericolosa, allora rendila astratta - o preferibilmente rendila meno pericolosa, se possibile ;-)

Pensalo come un conto bancario:

Puoi creare un account di base astratto generico chiamato " Account " ;, che contiene informazioni di base come i dettagli del cliente.

Puoi quindi creare due classi derivate chiamate " Account risparmio " o " DebitAccount " che possono avere il loro comportamento specifico mentre beneficiano del comportamento della classe base.

Questa è una situazione in cui il cliente deve avere un Conto di risparmio o un Conto di addebito, un Conto "quot" generico "; non è consentito in quanto non è molto popolare nel mondo reale non avere un account senza descrizione.

Se riesci a creare uno scenario simile per le tue esigenze, l'abstract è la strada da percorrere.

Le classi astratte sono per le classi parzialmente implementate.

Di per sé non ha senso avere un'istanza di una classe astratta, deve essere derivata. Se desideri essere in grado di creare la classe base, questa non può essere astratta.

Mi piace pensare alle classi astratte come interfacce che hanno alcuni membri predefiniti poiché sono comuni a tutte le sottoclassi.

Pensa a questo in un modo diverso

  

La mia classe base è un oggetto completo da sola?

Se la risposta è no, allora rendila astratta. Se è sì, probabilmente vorrai renderlo una classe concreta.

Direi che se non hai intenzione di chiamare la classe base da sola, allora dovresti definirla una classe astratta.

Dipende dal fatto che tu voglia implementare la classe base da sola oppure no.

Come classe astratta, non puoi ricavarne oggetti.

Le classi astratte sono ottime per funzionalità predefinite, ad esempio - quando conoscono il comportamento esatto minimo che una classe dovrebbe esporre ma non quali dati dovrebbe usare per farlo o l'implementazione esatta.

abstract class ADataAccess
{
    abstract public void Save();
}

Le classi normali (non astratte) possono essere ottime per cose simili ma devi conoscere i dettagli dell'implementazione per poterle scrivere.

public class DataAccess
{
    public void Save()
    {
        if ( _is_new )
        {
            Insert();
        }
        else if ( _is_modified )
        {
            Update();
        }
    }
}

Inoltre, è possibile utilizzare le interfacce (individualmente o sulle classi, astratte o meno) per definire lo stesso tipo di definizione del prototipo.

interface ISaveable
{
    void Save();
    void Insert();
    void Update();
}

class UserAccount : ISavable
{
    void ISavable.Save() { ... }
    void ISavable.Insert() { ... }
    void ISavable.Update() { ... }
}

Ancora un'altra opzione potrebbe essere l'uso di generici

class GenDataAccess<T>
{
    public void Save()
    {
        ...
    }
}

Tutti questi metodi possono essere usati per definire un certo prototipo per le classi con cui lavorare. Modi per assicurarsi che il codice A possa parlare con il codice B. E ovviamente puoi combinare tutto quanto sopra a tuo piacimento. Non esiste un modo giusto definito, ma mi piace definire interfacce e classi astratte, quindi fare riferimento alle interfacce. In questo modo si eliminano alcuni dei requisiti di pensiero per "impianto idraulico" nelle classi di livello superiore mantenendo la massima flessibilità. (avere interfacce toglie il requisito di usare la classe base astratta, ma la lascia come opzione).

Penso che molti di voi dovrebbero tornare nuovamente alle classi OO di base.

Il principio di base di base in OOA / OOD è di astrarre astratto astratto, fino a quando non puoi più astrarre. Se quello che stai guardando è un'astrazione, allora così sia, questo è ciò che il tuo OOA / OOD ti ha già detto. Tuttavia, se ti siedi lì a chiederti se "codice" dovrebbe essere astratto o no, quindi ovviamente non sai cosa significa il termine e dovresti andare a imparare di nuovo OOA / OOD / OOP di nuovo :-)

Più al punto che dovresti imparare Design Patterns e Harmonic Theory, questo ti aiuterà immensamente con i tuoi progetti OO!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top