Domanda

Ho un'interfaccia A, per la quale devo fornire alcuni diversi implementazioni. Tuttavia, tali implementazioni condividono alcuni metodi di supporto, quindi Ho spostato quei metodi in una classe base astratta.

Interface A {
    void doX();
}

abstract Class B implements A {
    protected void commonY() {
        // ...
    }

    @Override
    public abstract void doX();
}

Class C extends B {
    @Override
    public void doX() {
        // ...
    }
}

Class D extends B {
    @Override
    public void doX() {
        // ...
    }
}

Il mio codice funziona come previsto, ma ho alcune domande:

  • Devo dichiarare il metodo astratto doX () in Classe B? Perché (no)?

  • Dovrei anche dichiarare esplicitamente " implementa A " su classe C e D? Perché (no)?

È stato utile?

Soluzione

Penso che sarebbe meglio farlo come segue:

Interface A {
        void doX();
}

abstract Class B {
        protected void commonY() {
                // ...
        }
}

Class C extends B implements A{

        public void doX() {
                // ...
        }
}

Class D extends B implements A{

        public void doX() {
                // ...
        }
}

Non dovresti mescolare l'interfaccia (firma dei metodi) con l'implementazione.

Altri suggerimenti

  • Devo dichiarare il metodo astratto doX () in Classe B? Perché (no)?

No. È una classe astratta: definire l'interfaccia significherà che tutte le sottoclassi dovranno implementare quei metodi. In altre parole, è ridondante.

  • Dovrei anche dichiarare esplicitamente " implementa A " su classe C e D? Perché (no)?

No, ancora una volta - poiché la tua superclasse (classe base astratta) implementa tale interfaccia, le tue sottoclassi concrete saranno garantite per implementare tale interfaccia.

Aggiungerò solo l'altra opzione.

Trasforma la classe astratta B in una classe AUtil che non implementa A. Le firme del metodo potrebbero richiedere un argomento aggiuntivo di tipo A per funzionare.

C e D implementano A e istanziano AUtil internamente. Ciò consente a C e D di estendere altre classi.

Sono d'accordo con JeeBee: considera la possibilità di implementare i tuoi metodi di supporto in un posto diverso da una classe base astratta.

Se il tuo metodo helper commonY () esiste solo nella classe base B astratta, tutte le classi che implementano l'interfaccia A dovranno estendere anche la classe base B per sfruttare l'implementazione di commonY (). Ma potresti non voler sempre essere costretto a estendere la classe B.

Inoltre, cosa succede se si desidera modificare l'implementazione di commonY () in futuro? Interesserai quindi a molte implementazioni dell'interfaccia A. Ma se non controlli tutte queste implementazioni dell'interfaccia A, potresti influenzarne la funzionalità (in modo negativo) senza volerlo.

L'uso di una classe base astratta in questa situazione può semplicemente togliere un po 'di flessibilità senza darti nulla in cambio.

Una classe astratta che implementa un'interfaccia deve implementare quell'interfaccia. In particolare, deve disporre di un metodo pubblico per ogni nome e firma del metodo specificati in tale interfaccia.

L'ereditarietà è transitiva. Non è necessario scrivere che la classe C implementa l'interfaccia A se la classe C deriva la classe B che implementa l'interfaccia A. Tuttavia, non vi è nemmeno molto danno ad essa.

Non dichiarerei doX() in B e non aggiungerei " implements A " su C e D perché non ripeterti .

L'estratto A in implements non aggiunge nulla, poiché è già specificato da " <=> " ;. Lo stesso vale per l'aggiunta di & Quot; <=> & Quot; a <=> e <=>.

L'unico uso possibile per quelle clausole sarebbe la documentazione: se vuoi rendere molto esplicito che <=> (o <=>) è-a <=>, allora potresti aggiungere <=>, ma tu dovresti essere consapevole che in realtà non ha importanza per il compilatore.

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