2010-02-24 10 views
8

Sono passato da Java 1.4 (azienda precedente) a Java 1.6 (nuova società). Quello che ho osservato è che nel caso della 1.4 la maggior parte dei framework proprietari sono stati definiti usando interfacce e modelli di template, mentre con 1.6 la maggior parte dei framework sono definiti intorno ai generici.Generics vs. Interfaces

Mentre sto ancora cercando di afferrare Generics, la mia domanda è: è un approccio di progettazione corretto? Le interfacce rendono il tuo design più flessibile/disaccoppiato. Considerando che Generics, implementa il tipo di sicurezza e ti impone di passare attorno a un tipo specifico di classe. Non aiuta davvero a disaccoppiare il tuo codice. È corretto?

Un esempio -

public MyWizard extends SignupWizard<SignupSection, SignupObject, SignupListener, SignupView>{ 
} 

invece il design sarebbe più flessibile se fosse ..

public interface Wizardable{ 
    public SignableSection getSection(); 
    public SignableObject getSignableObject(); 
... 
} 

public MyWizard implements Wizardable{ 
.... 
} 
+1

Si prega di migliorare il vostro esempio. Ad esempio, qual è la definizione di SignupWizard? Fornisci alcuni esempi concreti di quadri in cui i farmaci generici vengono utilizzati nel modo in cui parli. La questione dei "generici contro interfacce" non ha molto senso per me, perché spesso vengono usati insieme. "Annotazioni contro interfacce" ha più senso. –

+0

Sembra il tipo di cosa che mi aspetterei in C++, non in Java. –

risposta

4

Non direi nulla di generico o di interfaccia, ognuno ha i suoi diversi bisogni e usi. L'utilizzo di parametri generici nel modo indicato nel post originale ha più finalità. Consente agli sviluppatori di definire le classi base che costituiscono i tipi di oggetto di campo della classe. Usando questo, lo sviluppatore può accettare oggetti di classe come parametri su cui è possibile utilizzare la riflessione per creare gli oggetti reali e impostare i campi, o semplicemente accettare l'intero oggetto da impostare in primo luogo.Il problema relativo alla necessità di oggetti di classe anziché eseguire new T() o tale è noto come type erasure.

Un altro vantaggio dell'utilizzo di generici è che non è necessario digitare tutto il tempo quando si utilizzano campi o metodi da una superclasse - si conosce personalmente il loro tipo, ma Java non dispone di quel tipo di informazioni memorizzate da nessuna parte. Un ulteriore vantaggio è che tutti i metodi getter/setter possono utilizzare i parametri generici ed esporre un fronte più sensibile ad altri oggetti che si basano sul fatto che si impostano campi specializzati nell'oggetto summenzionato.

Il problema con l'utilizzo delle interfacce per fare la stessa cosa che fa il generatore è che sono necessari metodi aggiuntivi per accedere ai tipi specializzati e lanciarli, prima di restituirli (o controllare i tipi in arrivo e quindi impostare i campi sugli oggetti). Sta rendendo il design più complesso e in realtà non aiuta affatto a disaccoppiare.

Come ho menzionato in un commento, qualsiasi sottoclasse imposterà quei parametri di tipo e non esporrà nulla all'utente. Quindi puoi avere qualcosa come class MegaSignupWizard extends SignupWizard<MegaSignupSection, MegaSignupObject, MegaSignupListener, MegaSignupView> e tutto rimane perfettamente valido con MegaSignupWizard avendo accesso a metodi specializzati nelle classi senza alcuna necessità di trasmettere. Ora è bello :)

1

Ho notato che molti dei nuovi quadri tendono ad utilizzare le annotazioni invece di interfacce , ma non li ho notati usando generici invece di interfacce (qualunque cosa significhi - per favore spiegane di più).

Con l'aiuto di farmaci generici, la sua possibilità di ridurre alcuni duplicazione del codice e di migliorare la sicurezza tipo, quando si dispone di un interfaccia con i parametri di tipo generico e la stessa interfaccia lavorerà per un sacco di tipi diversi. Le raccolte nel pacchetto java.util sono un buon esempio di quando i generici sono utili.

Nel caso di annotazioni, a volte mi sento che sono abusate e un'interfaccia sarebbe migliore - ad esempio con un'interfaccia è facile sapere quali parametri un metodo dovrebbe assumere - ma in altri casi un'annotazione è più flessibile e potente .

+0

Annotazioni anziché interfacce ?! Che cosa sarebbe un tale quadro? –

+1

Ad esempio l'annotazione @GET nell'API Servlet 3.0: http://today.java.net/article/2008/10/08/introduction-servlet-30 –

+0

@Murali: mai sentito parlare di JPA? Quasi solo annotazioni. – whiskeysierra

3

Generics consente di implementare metodi sul tipo generale mentre le interfacce definiscono solo le firme. Forse a volte viene abusato per comportarsi come lo trait di Scala, ma per lo più hanno due scopi diversi. Se tutto era un'interfaccia, ci sarà un sacco di codice duplicato o delegazioni per qualche classe di supporto.

0

Dai un'occhiata a Jung2 per vedere dove i Generics diventano davvero potenti. Fondamentalmente, qualsiasi oggetto può essere un vertice o un bordo che rende alcune idee davvero interessanti negli algoritmi di rete. Non puoi farlo solo con le interfacce.

Non sono sicuro che il tuo uso sopra sia buono. Se stai estendendo da un oggetto o implementando un'interfaccia, non vuoi veramente passare oggetti del genere. I generici sono usati per implementare una classe con un tipo astratto, come una collezione, che potrebbe agire su qualsiasi cosa. Cosa succede se passo SignupWizard<int, int, int, int> che è perfettamente valido?

Per questa particolare idea, forse si desidera utilizzare le interfacce. Avere un'interfaccia che definisce wizardaction, ogni oggetto che lo implementa e mywizard che è in grado di .addaction (int position, action wizardaction). In realtà questo è sicuramente un problema di interfacce.

Sono d'accordo con gli altri: i generici sono stati utilizzati quando sono necessari dalle biblioteche.

+0

Se il vertice e il bordo hanno una super interfaccia, allora un oggetto può essere vertice o un bordo. –

+0

Ma non è possibile avere parametri digitati sui bordi. Devi usare l'oggetto o bastone per un tipo. – whiskeysierra

+0

È perfettamente valido. Qualsiasi sottoclasse imposterà quei parametri tipo e non esporrà nulla all'utente. Quindi puoi avere qualcosa come MegaSignupWizard estende SignupWizard e tutto rimane perfettamente valido con MegaSignupWizard che ha accesso a metodi specializzati nelle classi senza bisogno di cast. –

1

Penso che siano generici e interfacce, dal momento che qualsiasi interfaccia può utilizzare i generici stessi. Il problema che vedo quando si inizia a utilizzare le classi generiche (astratte) si perde la flessibilità dell'uso della composizione. Mentre non c'è niente di male nell'ereditarietà in quanto tale devi progettare per questo e ci sono molte insidie.

+0

Giusto, e uno dei punti di Bloch in "Effective Java" è quello di favorire la composizione sull'ereditarietà. La mia teoria, ogni volta che vedo un uso intenso di classi generiche e astratte, è che i programmatori non hanno familiarità con le interfacce e con gli ultimi giocattoli in Java (Generics, Annotations). Quindi, quando guardiamo tutti i quadri là fuori come risposte, non significa necessariamente che questa è l'unica vera strada da percorrere. Solo il tempo dimostrerà se il loro design è stato robusto e malleabile credo, cioè sarà intorno a qualcosa come log4j. – michaelok