Utilizzo di metodi astratti per forzare le sottoclassi per definire i valori per i campi membri

5

Spesso nei miei progetti definisco una superclasse astratta le cui sottoclassi variano per lo più nei loro valori per i campi definiti nella superclasse.

Ad esempio, in un gioco che sto sviluppando c'è una classe astratta Missile con un numero di sottoclassi. Ognuno definisce un valore diverso per le variabili membro come MAX_SPEED , MASS , FLYING_FORCE , che vengono quindi utilizzate nei calcoli eseguiti nella superclasse.

Uso metodi astratti in Missile per forzare le sue sottoclassi a definire queste variabili. Ad esempio, ho semplicemente un metodo astratto defineMass() che costringe le sottoclassi a definire il proprio valore di massa.

Un esempio diverso potrebbe essere la mia Entity class (la superclasse di tutte le classi di gioco) che definisce un metodo loadImage() astratto che costringe le sottoclassi a definire un'immagine per se stessi.

Questa è una buona pratica? È comune?

    
posta Aviv Cohn 29.06.2014 - 01:57
fonte

4 risposte

4

Penso che l'ereditarietà meriti uno scopo migliore:

  • Se l'unica cosa che varia tra le sottoclassi e tra le sottoclassi e la sua superclasse sono i valori di alcuni membri, allora si sta abusando dell'eredità o si sta usando male. È possibile utilizzare il modello di builder per creare missili con valori diversi. Se il modello di builder è troppo complesso per l'attività, i metodi di fabbrica come buildMissileOfTypeA() e buildSuperMassiveMissile() lo farebbero.
  • Metteresti l'ereditarietà se i metodi astratti fossero correlati a comportamenti che le sottoclassi implementerebbero in modi potenzialmente diversi, ma non solo per impostare un valore di un membro.
  • Inoltre, non stai forzando realmente le sottoclassi a definire il loro valore, ma semplicemente possono implementare un metodo vuoto che non modifica il valore della massa e il compilatore sarà soddisfatto.
risposta data 29.06.2014 - 02:13
fonte
1

Se si desidera forzare una sottoclasse per impostare il campo membro corretto, è possibile specificare un costruttore con tutti i parametri necessari nella superclasse e quindi forzare le sottoclassi a chiamare il costruttore (a condizione che la lingua scelta imponga di chiamare super costruttori).

    
risposta data 29.06.2014 - 20:29
fonte
1

Inserirò questi campi nel costruttore, ad es.

public abstract class Missile
{
    int MAX_SPEED, MASS, FLYING_FORCE

    Missile(int maxSpeed, int mass, int flyingForce)
    {
        MAX_SPEED = maxSpeed;
        MASS = MASS;
        FLYING_FORCE = flyingForce;
    }
}

E quindi crea le classi figlie come segue, ad es.

public class Rocket extends Missile
{
     Rocket()
     {
         super(100, 20, 50);
     }
}

Quindi i campi devono essere dichiarati ogni volta che viene chiamata la classe Missile, ma può essere davvero ordinatamente cablata nelle sue classi figlie.

    
risposta data 26.11.2016 - 18:27
fonte
0

È un pattern che ho visto e utilizzato spesso, e lo vedo come una forma del modello Metodo del modello .

Considera una classe BasePlugin , ad esempio, che definisce proprietà Name e SupportedTypes . Queste proprietà vengono utilizzate come parte delle implementazioni condivise della classe base: utilizzando Name per la registrazione, forse, o utilizzando SupportedTypes per la convalida. Questo potrebbe essere in aggiunta alla logica sovrascritta di ExecutePlugin o qualsiasi altra cosa.

Una modifica che farei dal tuo progetto è definire un metodo getMass (o, se in C # o un linguaggio simile, una proprietà con un getter) piuttosto che il tuo defineMass . Il nome di getMass implica che il suo utilizzo sia come getter, utilizzato ovunque nel codice della classe base in cui il valore è neede. defineMass implica che verrà chiamato nel costruttore e, di per sé, memorizzerà un valore in un campo nella classe base. Ciò sembra non necessario e fa sì che defineMass abbia effetti collaterali (che potrebbero avere effetto sul codice multithreaded) o, in alternativa, non sia un nome molto descrittivo, assumendo che ha intenda che sia un getter.

Invece di "forzare la classe derivata a definire i valori", che è solo un modo per dire "Ho bisogno dei valori della classe derivata", semplicemente chiedi la classe derivata per il valore e lascia fa tutto ciò che è necessario per dartelo.

    
risposta data 29.06.2014 - 19:46
fonte

Leggi altre domande sui tag