2010-02-24 8 views
8

Ich wechselte von Java 1.4 (frühere Firma) zu Java 1.6 (neue Firma). Ich habe beobachtet, dass im Fall von 1.4 die meisten proprietären Frameworks unter Verwendung von Interfaces und Template-Mustern definiert wurden, während bei 1.6 die meisten Frameworks um Generics definiert sind.Generics vs. Interfaces

Während ich immer noch versuche, Generics in den Griff zu bekommen, ist meine Frage - Ist das ein richtiger Designansatz? Schnittstellen machen Ihr Design flexibler/entkoppelter. Während Generics, implementieren Typ Sicherheit und erzwingen Sie eine bestimmte Art von Klasse zu übergeben. Es hilft nicht wirklich beim Entkoppeln deines Codes. Ist das richtig?

Ein Beispiel -

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

statt das Design wäre flexibler, wenn es ..

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

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

Bitte verbessern Sie Ihr Beispiel. Zum Beispiel, was ist die Definition von SignupWizard? Geben Sie einige konkrete Beispiele für Frameworks an, in denen Generika so verwendet werden, wie Sie es nennen. Die Frage nach "Generika vs. Interfaces" ergibt für mich wenig Sinn, da oft beide zusammen verwendet werden. "Anmerkungen vs. Schnittstellen" macht mehr Sinn. –

+0

Sieht so aus, wie ich es in C++ erwarte, nicht in Java. –

Antwort

4

Ich würde nicht sagen, nichts war Generika vs Schnittstellen, jeder haben ihre unterschiedlichen Bedürfnisse und Anwendungen. Die Verwendung generischer Parameter in der im ursprünglichen Post erwähnten Weise dient mehreren Zwecken. Es ermöglicht Entwicklern, die Basisklassen zu definieren, aus denen die Feldobjekttypen der Klasse bestehen. Dadurch kann der Entwickler Klassenobjekte als Parameter akzeptieren, mit denen er die tatsächlichen Objekte erstellen und die Felder setzen oder einfach das gesamte Objekt übernehmen kann.Das Problem, das sich auf den Bedarf von Klassenobjekten bezieht, anstatt new T() oder dergleichen zu tun, ist als type erasure bekannt. Ein weiterer Vorteil der Verwendung von Generika ist, dass Sie nicht die ganze Zeit tippen müssen, wenn Sie Felder oder Methoden aus einer Superklasse verwenden - Sie kennen ihre Typen persönlich, aber Java hat diese Art von Informationen nirgendwo gespeichert. Ein weiterer Vorteil ist, dass all Ihre Getter/Setter-Methoden die generischen Parameter verwenden können und eine vernünftigere Front gegenüber anderen Objekten verfügbar machen, die darauf angewiesen sind, dass Sie spezialisierte Felder in dem oben genannten Objekt einrichten.

Das Problem mit der Verwendung von Schnittstellen, um die gleiche Sache, die Generika tut, ist, dass Sie zusätzliche Methoden für den Zugriff auf die spezialisierten Typen benötigen und sie umwandeln, bevor Sie sie zurückgeben (oder eingehende Typen überprüfen und dann Felder auf die Objekte festlegen). Es macht das Design komplexer und hilft nicht wirklich bei der Entkopplung.

Wie ich in einem Kommentar erwähnt habe, werden alle Unterklassen diese Typparameter setzen und nichts dem Benutzer aussetzen. So können Sie etwas wie class MegaSignupWizard extends SignupWizard<MegaSignupSection, MegaSignupObject, MegaSignupListener, MegaSignupView> haben und alles bleibt perfekt gültig mit MegaSignupWizard Zugang zu spezialisierten Methoden in den Klassen ohne irgendeine Notwendigkeit zu werfen. Nun, das ist cool :)

1

ich bemerkt habe, dass viele der neuen Frameworks neigen Anmerkungen anstelle von Schnittstellen zu verwenden , aber ich habe nicht bemerkt, dass sie Generika anstelle von Schnittstellen verwenden (was auch immer es bedeutet - bitte erklären Sie mehr).

Mit Hilfe von Generics, ist es möglich, einige Code-Duplizierung zu reduzieren und die Typsicherheit zu verbessern, wenn Sie eine Schnittstelle mit generischen Typparametern haben und die gleiche Schnittstelle für viele verschiedene Typen funktionieren wird. Die Sammlungen im Paket java.util sind ein gutes Beispiel dafür, wann Generika nützlich sind. Im Falle von Annotationen empfinde ich manchmal, dass sie überstrapaziert sind und eine Schnittstelle besser wäre - zum Beispiel mit einer Schnittstelle ist es einfach zu wissen, welche Parameter eine Methode verwenden sollte - aber in anderen Fällen ist eine Annotation flexibler und leistungsfähiger .

+0

Anmerkungen anstelle von Schnittstellen ?! Was wäre ein solcher Rahmen? –

+1

Zum Beispiel die @GET Annotation in der Servlet 3.0 API: http://today.java.net/article/2008/10/08/introduction-servlet-30 –

+0

@Murali: Hast du jemals von JPA gehört? Fast nur Anmerkungen. – whiskeysierra

3

Mit Generics können Sie Methoden für den allgemeinen Typ implementieren, während Schnittstellen nur die Signaturen definieren. Vielleicht wird es manchmal missbraucht, um wie Scalas trait zu handeln, aber meistens dienen sie zwei verschiedenen Zwecken. Wenn alles eine Schnittstelle war, wird es eine Menge doppelten Code oder Delegationen in einer Hilfsklasse geben.

0

Werfen Sie einen Blick auf Jung2, um zu sehen, wo Generika wirklich mächtig werden. Grundsätzlich kann jedes Objekt ein Eckpunkt oder eine Kante sein, die für einige wirklich interessante Ideen in Netzwerkalgorithmen sorgt. Sie können dies nicht mit nur Schnittstellen tun.

Ich bin mir nicht sicher, ob Ihre obige Verwendung auch gut aussieht. Wenn Sie von einem Objekt ausgehen oder eine Schnittstelle implementieren, möchten Sie solche Objekte nicht wirklich weitergeben. Generics werden verwendet, um eine Klasse mit einem abstrakten Typ wie eine Sammlung zu implementieren, die auf alles einwirken kann. Was passiert, wenn ich SignupWizard<int, int, int, int> passiere, was vollkommen gültig ist?

Für diese spezielle Idee möchten Sie vielleicht Schnittstellen verwenden. Eine Schnittstelle, die eine Wizard-Aktion definiert, wobei jedes Objekt sie implementiert und mein Wizard in der Lage ist, .addaction (int position, wizardaction action) zu implementieren. In der Tat ist das definitiv ein Schnittstellenproblem.

Ich würde mit den anderen übereinstimmen - Generika wurden verwendet, wenn sie von Bibliotheken benötigt werden.

+0

Wenn Scheitelpunkt und Kante über eine Superschnittstelle verfügen, kann ein Objekt ein Scheitelpunkt oder eine Kante sein. –

+0

Aber Sie können keine Parameter an den Kanten eingegeben haben. Sie müssen entweder ein Objekt verwenden oder an einem Typ festhalten. – whiskeysierra

+0

Es ist vollkommen gültig. Alle Unterklassen setzen diese Typparameter und geben dem Benutzer nichts aus. So können Sie etwas wie MegaSignupWizard erweitern SignupWizard und alles bleibt perfekt gültig mit MegaSignupWizard Zugriff auf spezielle Methoden in den Klassen, ohne zu müssen, zu müssen. –

1

Ich denke, es ist Generika und Schnittstellen, da jede Schnittstelle Generics selbst nutzen kann. Das Problem, das ich sehe, wenn Sie beginnen, generische (abstrakte) Klassen zu verwenden, verlieren Sie die Flexibilität der Verwendung der Zusammensetzung. Während es nichts Schlechtes an Erbschaft als solcher gibt, muss man dafür entwerfen und es gibt viele Fallstricke.

+0

Richtig, und einer von Blochs Punkten in "Effektives Java" ist, die Komposition über die Vererbung zu bevorzugen. Meine Theorie ist, dass Programmierer, wenn ich den starken Gebrauch von Generics und abstrakten Klassen sehe, einfach nicht so vertraut mit Interfaces sind wie mit den neuesten Spielzeugen in Java (Generics, Annotations). Wenn wir also alle Frameworks als Antworten betrachten, bedeutet dies nicht unbedingt, dass dies der einzig richtige Weg ist. Nur die Zeit wird beweisen, ob ihr Design robust und formbar war, denke ich, d. H. Wird das so lange sein wie Log4j. – michaelok