Wann ist die Verwendung von Generika und Vererbung angemessen?

7

Was sind die Situationen und die damit verbundenen Vorteile der Verwendung von Generics über die Vererbung und umgekehrt, und wie sollten sie am besten kombiniert werden?

Danke für die Antwort Jungs.

Ich werde versuchen, die Motivation für diese Frage so gut wie möglich zu benennen: Ich habe eine Klasse wie folgt:

%Vor%

Nun nehme ich an, dass ich ein Repository habe, das ein InformationReturn-Argument annimmt, das abhängig vom Typ des Info-Objekts T verschiedene Felder in einem DB abbilden soll. Ist es besser verschiedene Repositories für den Typ T zu erstellen? ein Repository, das Reflektion verwendet, um den Typ zu bestimmen; Oder gibt es einen besseren Weg, Vererbungsfähigkeiten über / mit Generika zu nutzen?

Hinweis : Ein anderer Client-Code muss auf der Grundlage des T-Typs ebenfalls anders funktionieren.

    
Laz 28.04.2009, 18:56
quelle

6 Antworten

4

Sie sind wirklich sehr unterschiedliche Ideen. Generika ermöglichen es Ihnen, allgemeine "spezifische" Funktionen (auf die Gefahr hin, oxymoronisch zu klingen) allgemein zu deklarieren. A List<int> funktioniert nicht anders als List<string> , abgesehen von der Art der Daten, die darin enthalten sind.

Während die Vererbung verwendet werden könnte, um dasselbe zu tun, könnte ich eine Klasse List und dann eine Klasse IntList und eine StringList erstellen, die von ihr erben. Ich könnte diese beiden Klassen leicht ganz anders funktionieren lassen oder eine Angebotsfunktionalität haben, die in der anderen nicht verfügbar ist.

Bearbeiten

Nach der Überprüfung der Bearbeitung der Frage lautet die Antwort sortof "es kommt darauf an." Sie können Argumente für beide Seiten erstellen - LINQ to SQL und das Entity Framework sind beide eine Kombination aus reflektiven Prüfungen mit Generika und stark typisierten Entitätsklassen und anderen Repository-Klassen. Sie können sicherlich den Ansatz, den Sie betrachten, einfach wissen, dass im Allgemeinen ein Problem, das entweder durch Reflexion oder mit etwas anderem gelöst werden kann, LIKE schneller wird, wenn es durch das "etwas anderes" gelöst wird. Es hängt davon ab, wie viel von einem Kompromiss zwischen Leistung, Wartungsfreundlichkeit, Lesbarkeit und Zuverlässigkeit gewünscht wird.

    
Adam Robinson 28.04.2009, 19:00
quelle
10

Generika und Vererbung sind zwei verschiedene Dinge. Vererbung ist ein OOP-Konzept und Generics sind eine CLR-Funktion, mit der Sie Typparameter zur Kompilierzeit für Typen angeben können, die sie verfügbar machen.

Vererbung und Generika funktionieren eigentlich ziemlich gut zusammen.

Vererbung:

Die Vererbung ermöglicht es mir, einen Typ zu erstellen:

%Vor%

und später einen anderen Typ erstellen, der Pen erweitert:

%Vor%

Dies ist hilfreich, da ich den gesamten Status und das Verhalten der Basisklasse wiederverwenden und neues Verhalten oder Status in FountainPen aufdecken kann. Durch die Vererbung kann ich schnell eine spezifischere Version eines vorhandenen Typs erstellen.

Generika:

Generics sind eine CLR-Funktion, mit der ich einen Typ wie diesen erstellen kann:

%Vor%

Wenn ich jetzt Foo<T> verwende, kann ich den Typ von T angeben, indem ich ein Argument vom Typ generic zur Verfügung stelle:

%Vor%

Nun, da ich angegeben habe, dass T ein int für das Objekt sein soll, das ich gerade erstellt habe, ist der Typ von Foo.Bar auch int seit der Deklaration vom Typ T .

    
Andrew Hare 28.04.2009 18:58
quelle
7

Verwenden Sie Generics, um ein Verhalten eines Algorithmus oder Typs anzugeben, das in Form eines "unbekannten Typs" ausgedrückt werden kann, während eine API beibehalten wird, die in Bezug auf diesen unbekannten Typ stark typisiert ist. Der unbekannte Typ ist als -Typ-Parameter bekannt und wird im Code wie folgt ausgedrückt:

%Vor%

(etc) - hier ist T der Typparameter. Generische Methoden sind ähnlich:

%Vor%

Der aufrufende Code gibt das Typ-Argument an, mit dem es arbeiten möchte, z. B.

%Vor%

Verwenden Sie Vererbung, um das Verhalten eines Typs zu spezialisieren.

Ich kann mir wirklich nicht viele Orte vorstellen, wo sie Alternativen zueinander sind ...

    
Jon Skeet 28.04.2009 19:01
quelle
4

Ich denke, Sie sollten Generika verwenden, wenn Sie nur die gleiche Funktionalität für verschiedene Typen verwenden möchten (Hinzufügen, Entfernen, Zählen), und es wird auf die gleiche Weise implementiert. Vererbung ist, wenn Sie die gleiche Funktionalität (GetResponse) benötigen, aber es auf verschiedene Arten implementiert werden soll.

    
C. Ross 28.04.2009 19:01
quelle
4

Verwenden Sie Generika, wenn Sie eine "Vorlage" erstellen möchten, die auf viele Stile unbekannter Klassen angewendet werden kann. Z.B. Sammlungen halten ??? sind gute Kandidaten für Generika. Vererbung ist für, wenn Sie eine Basis haben, dass Kinder "sind" eine Erweiterung dieses Konzepts.

Meine allgemeinen Regeln

  • Wenn Sie anfangen, in Ihrem Code Eigenschaften als Objekt zu definieren und viel Casting eingeben, dann ist es wahrscheinlich Zeit für Generika.
  • Wenn Sie gegen das "höhere Konzept" und die abgeleitete Klasse programmieren wollen, dann ist die Vererbung.
  • Wenn Ihre Klasse eine Concerte-Klasse umschließen oder bearbeiten wird, dann ihre Generika.
  • Wenn Sie sich auf die Besonderheiten einer unbekannten "noch zu definierenden" Klasse verlassen, dann sind Sie wahrscheinlich besser mit Generika.
  • Wenn Sie abgeleitete Klassen sind "ist ein" dann ist es normalerweise Vererbung
  • Wenn Ihre Oberklasse "einige x verwendet", dann ihre Generika.
Robin Vessey 02.05.2009 01:29
quelle
3

Bei der Vererbung geht es viel mehr um "is-a" (Frosch ist ein Tier), bei dem es bei Generika darum geht, Container zu erstellen, die auf typisierte Daten reagieren (Liste von T, Prozessor von T, usw.). Sie schließen sich nicht gegenseitig aus .

Sie können dies haben, wenn Sie möchten:

%Vor%     
Brian Genisio 28.04.2009 18:59
quelle

Tags und Links