C # deklariert sowohl Klasse als auch Schnittstelle

7
%Vor%

Was soll ich in die ?? Objekte erben, die von Animal und IHasLegs erben? Ich möchte kein Snake in diesem Käfig sehen und auch kein Table .

-------------- BEARBEITEN --------------

Vielen Dank für Ihre Antworten, aber hier ist die Sache: Was ich eigentlich machen möchte, ist folgendes:

%Vor%

TextBox / ComboBox ist natürlich ein Control. Jetzt, wenn ich eine abstrakte Klasse erstelle, die sowohl Control als auch IClonable erbt, verliere ich die TextBox / ComboBox-Vererbung, die ich brauche. Mehrfache Klassenvererbung ist nicht erlaubt, daher muss ich mit Schnittstellen arbeiten. Jetzt, wo ich wieder darüber nachdenke, könnte ich eine andere Schnittstelle erstellen, die von IClonable erbt:

%Vor%

und dann

%Vor%

Danke !!

    
Stefanos Kargas 29.10.2013, 14:11
quelle

6 Antworten

3

Warum machst du nicht eine Klasse AnimalwithLegs?

%Vor%

dann

%Vor%     
gsharp 29.10.2013, 14:18
quelle
17

Zunächst ist Animals eine schlechte Wahl für einen Klassennamen, es wäre Animal . Klassennamen sollten in Singular sein. Diese Klasse sollte auch als abstract deklariert werden, da sie nur eine Basisklasse für konkrete Typen wie Donkey ist.

Zweitens können Sie eine abstrakte Klasse namens LeggedAnimal definieren, die von Animal und IHasLegs erbt. Und dann können Sie Donkey von LeggedAnimal usw. erben.

Schließlich kannst du dann List<LeggedAnimal> sagen und du kannst loslegen!

    
Roy Dictus 29.10.2013 14:14
quelle
10

Es gibt kein direktes Konzept von List<T where T : Animals, IHasLegs> . Sie können die T um eine Stufe in den Käfig verschieben - aber dann muss der Aufrufer eine einzelne T angeben, die beide Bedingungen erfüllt:

%Vor%

Es könnte zum Beispiel ein Cage<Lizard> sein - oder (separat) ein Cage<Donkey> - aber Sie konnten dies trotzdem nicht zum Speichern von any verwenden Animal das hat Beine - dh du könntest kein Lizard und kein Donkey im gleichen Käfig mit diesem Konzept setzen.

    
Marc Gravell 29.10.2013 14:15
quelle
3
  1. Ich denke, dass Animal eine abstrakte Klasse ist und daher als INimal bezeichnet werden muss.
  2. Erstellen Sie einen neuen Typ IAnimalWithLegs, der sowohl von IhasLegs als auch von IAnimal erbt.
  3. Verwenden Sie den neu erstellten Typ als Typ der Liste.
user844541 29.10.2013 14:15
quelle
1

Sie haben ein vollständiges Beispiel .. Kopieren-Einfügen in Visual-Studio und kompilieren. Viel Glück:)

%Vor%     
G.Y 29.10.2013 14:40
quelle
0

Ein Ansatz, wenn es eine vernünftige Anzahl von Kombinationen von Typen gibt, an denen Sie interessiert sind, besteht darin, zusammengesetzte Schnittstellen zu definieren, die von mehreren Schnittstellen erben. Man kann eine zusammengesetzte Schnittstelle für jede Kombination von Schnittstellen definieren und einen solchen Typ als generischen Parameter verwenden. Das größte Problem bei diesem Ansatz ist, dass es keine Möglichkeit gibt, dies zu spezifizieren, auch wenn eine Schnittstelle wie IFooBar einfach IFoo und iBar ist und keine eigenen Mitglieder deklariert, also jede Klasse, die IFoo und% co_de implementiert % implementiert alle Mitglieder von IBar , die nicht zulassen, dass solche Klassen in IFooBar umgewandelt werden, es sei denn, sie deklarieren sich als Implementierung. Folglich muss man entscheiden, welche Kombinationen von Schnittstellen man interessiert, bevor man Klassen definiert, die diese Kombinationen von Schnittstellen implementieren, wenn diese Klassen durch Code verwendbar sein sollen, der diese Kombinationen erwartet.

Ein alternativer Ansatz besteht darin, eine Schnittstelle IFooBar zu definieren und für viele Ihrer anderen Schnittstellen (z. B. ISelf<out T> { T Self {get;}} ) auch z. IAnimal und einen beliebigen Typ, z. IAnimalAnd<out T> : IAnimal, ISelf<T> { } , die z.B. Zebra implementiert auch IAnimal . Wenn man dieses Muster verwendet und eine Liste von IAnimalAnd<Zebra> benötigt, von denen bekannt ist, dass sie Animal , IWagTail und IMoo unterstützen, dann wird% ce_de%, das diese Dinge gemäß dem Muster tut, IGiveMilk ( man kann die Schnittstellen in beliebiger Reihenfolge verschachteln). Wenn man eine Referenz Animal dieses Typs hat, wird IWagTailAnd<IMooAnd<IGiveMilkAnd<Animal>>>> it implementieren, it wird IWagTail implementieren, it.Self wird IMoo implementieren, und it.Self.Self wird IGiveMilk . Wenn it.Self.Self.Self das Muster in der üblichen Weise implementiert, beziehen sich alle oben genannten Referenzen auf die gleiche Objektinstanz Animal , aber als unterschiedliche Typen.

Was bei diesem Ansatz hilfreich ist, ist, dass ein Objekt, das eine beliebige Kombination von Schnittstellen unter Verwendung dieses Musters implementiert, in verschachtelten Schnittstellentypen umgewandelt werden kann, die eine Teilmenge dieser Typen darstellen, unabhängig davon, ob irgendjemand dachte, dass eine bestimmte Teilmenge beim Typ nützlich wäre wurde geschrieben. Die größte Schwierigkeit bei diesem Ansatz besteht darin, dass, obwohl ein Objekt, das it implementiert, sowohl it als auch IWagTailAnd<IGiveMilkAnd<Animal>> erwartet, der Compiler das nicht erkennen kann; es kann sagen, dass das Objekt IWagTail implementiert, und dass seine IGiveMilk -Eigenschaft IWagTail implementiert und man könnte erwarten, dass bei normalen Implementierungen des Musters die Self -Eigenschaft des Objekts auf sich selbst verweist (was bedeutet, dass es implementiert werden muss) IGiveMilk ), aber der Compiler kann das nicht wissen.

    
supercat 29.10.2013 21:21
quelle