Quando non usare una super classe astratta?

2

Esiste un caso / necessità di utilizzo (dal punto di vista della progettazione o dell'implementazione) per non rendere un abstract super-classe?

Ci sono delle differenze nel linguaggio di programmazione in uso?

Per fare un esempio:

abstract class A { /*...*/ }
class B extends A { /*...*/ }

La mia domanda riguarda A : quando non posso usare abstract o posso dichiarare la regola di Michael Dorner:;)

A good design comes always with an abstract (and not a concrete) superclass.

    
posta Michael Dorner 21.11.2016 - 15:04
fonte

3 risposte

5

Sempre, non puoi evitarlo (in Java)

Ogni classe ha una superclasse non astratta, non finale: Oggetto.

Giustamente o erroneamente i progettisti di Java sentivano che c'erano alcune azioni speciali che dovrebbe essere sempre disponibile e avere sempre un'implementazione predefinita.

In particolare, Equals e GetHashCode consentono di inserire qualsiasi cosa nei contenitori e quindi di cercare, per identità.

    
risposta data 22.11.2016 - 10:19
fonte
1

In parole povere:

(Userò Java nei miei esempi, per favore estrapola alla tua lingua di scelta, se possibile)

  • Non esiste un modificatore superclass . Esiste un modificatore final , tuttavia, che impedisce a chiunque di estendere la tua classe.
  • Quindi, se creo una classe concreta A , non so se qualcuno la estenderà nell'anno 2525. Ogni classe non finalizzata potrebbe diventare una superclasse un giorno.
  • Arriva l'anno 2525 e qualcuno estende la mia classe A

    public B extends A{
    }
    
  • Ora A è una superclasse. All'inizio non era una superclasse. Non avevo previsto che qualcuno lo estenderebbe nell'anno 2525.

Quindi il caso d'uso della superclasse non astratta è che era una classe concreta (ma non ancora una superclasse) per cominciare, non l'hai dichiarata esplicitamente come final , e qualcuno in futuro l'ha estesa, rendendolo una superclasse.

Un altro caso d'uso è che vuoi che la classe sia in grado di essere istanziata e allo stesso tempo aperta per l'estensione futura. Questa è la logica dietro il principio di apertura / chiusura, è possibile estendere le classi concrete e quelle astratte.

Bottom-line: non puoi prevedere che una classe concreta non venga estesa in qualsiasi momento, a meno che tu non faccia ogni finale di classe concreto per evitare che diventi mai una superclasse di un'altra classe. D'altra parte preferisco aderire al principio di inversione di dipendenza che afferma che nessun componente più alto dovrebbe dipendere da componenti inferiori, entrambi dovrebbero dipendere dalle astrazioni.

    
risposta data 21.11.2016 - 15:25
fonte
0

, ci sono casi in cui la super classe dovrebbe non essere astratta. Almeno nell'uso di Java della nozione di abstract . Se rendi una classe astratta o no è circostanziale.

Le classi astratte dovrebbero essere utilizzate quando la classe che stai descrivendo è incompleta da sola. Ad esempio:

public abstract class Animal{
    public abstract boolean hasBeak();
}

La classe sopra rappresenta un animale astratto. Nel nostro programma abbiamo deciso che la cosa importante degli animali è se hanno un becco o meno. Ovviamente, questo dipende dal tipo di animale che è. Quindi le sottoclassi di Animal, Goose o Bear, ad esempio, implementeranno il metodo astratto "hasBeak ()" e Goose and Bear sono classi che hanno abbastanza informazioni per implementare hasBeak () e restituire true o false .

La classe Bear, tuttavia, potrebbe non essere astratta. Potresti avere:

public class Bear extends Animal {
    protected location = "The Rockies";

    public boolean hasBeak(){return false;};

    public String getLocation(){return this.location;};
}

Questo è un caso in cui abbiamo deciso che un Orso non è astratto. Ci sono abbastanza informazioni che vogliamo essere in grado di creare istanze della classe Bear senza ulteriori informazioni / requisiti.

Ora possiamo avere:

public class PolarBear extends Bear {
    int sealCount;
    public PolarBear()
    {
        this.location = "The Arctic";
        this.sealCount = 0;
    }

    public void ateSeal()
    {
        this.sealCount++;
    }

    public int getSealCount(){
        return this.sealCount;
    }
}

In questo esempio Bear è davvero una super classe, ed è not abstract ed è valida e significativa. Qui, vogliamo che PolarBear ottenga tutti i vantaggi del codice che abbiamo scritto per Animal e Bear, ma quanti sigilli sono mangiati è unico per gli orsi polari, quindi ha senso estendere l'orso ma per la logica / informazione del sigillo di essere esclusivi per la classe dell'orso polare.

Potresti pensare a te stesso, "Giusto, ma la tua classe di alto livello è ancora astratta in questo esempio." Sì, ma è solo una circostanza. Questo esempio è ancora valido se rimuoviamo completamente la classe Animal (e rimuoviamo l'estensione dalla classe Bear). Ora abbiamo assunto un programma che si occupa esclusivamente di orsi, ed è ragionevole e valido avere un oggetto Bear istanziato, ma è anche una super classe non astratta per PolarBear classe.

    
risposta data 21.11.2016 - 17:41
fonte