2015-04-21 5 views
6

Ich möchte eine
Klasse X kann (this) dem
erbt von A (Basis)
die Methoden der B ausführen schreiben (?) Und die Mitglieder
implementieren müssen von C (Schnittstelle).Gibt es so etwas wie eine Klasse, die implementiert werden kann?

Implementieren von A und C sind kein Problem. Aber da X nicht von mehreren Klassen abgeleitet werden kann, scheint es unmöglich zu sein, dass X die Logik von A und B erbt. Beachte, dass A die sehr wichtige Basisklasse ist und B fast eine Schnittstelle ist, aber ausführbares Verhalten enthält. Der Grund, warum ich nicht möchte, dass B eine Schnittstelle ist, liegt darin, dass das Verhalten für jede Klasse, die es erbt oder implementiert, gleich ist.

Muss ich wirklich B als Schnittstelle deklarieren und die exakt gleichen 10 Codezeilen für jedes X implementieren, das das Verhalten von B benötigt?


2 Monate später
Ich bin derzeit Lernen C++ für sie in UE4 (Unreal Engine 4) verwendet wird.
Da C++ ist viel weniger streng als C# es einen tatsächlich enthält Muster Implementierung idom Begriff, der dieses Verhalten beschreibt: Diese mixin s genannt werden.

Sie können einen Absatz über die C++ - Mischung here auf Seite 9 (zweiter Absatz) lesen.

+2

Warum erben Sie einfach B von A oder umgekehrt? –

+3

Warum können Sie hier keine Komposition verwenden? Delegieren Sie die Methoden von B an eine Instanz von B ...(Es ist sehr schwierig, über so etwas auf eine so abstrakte Art zu sprechen. Es wäre hilfreicher, wenn Sie ein konkretes Beispiel geben würden.) –

+0

@ k4rlsson Weil nicht jedes X B benötigt (der Entwickler sollte es implementieren können) oder nicht) –

Antwort

5

bis Sie wirklich, dass ich B als Schnittstelle erklären und umsetzen müssen exakt die gleichen 10 Zeilen Code für jede X, die die sein muss Verhalten von B?

Ja und nein. Sie müssen B eine Schnittstelle machen. Implementierungen allgemeiner Methoden sollten jedoch nicht für alle Implementierungen der Schnittstelle dupliziert werden. Stattdessen sollten sie eine Klassenerweiterung für die Schnittstelle gehen in B:

public interface B { 
    void MethodX(); 
    void MethodY(); 
} 
public static class ExtensionsB { 
    public static void MethodZ(this B b) { 
     // Common implementations go here 
    } 
} 

Erweiterungsmethoden bieten eine Möglichkeit, Implementierungen zu teilen „horizontal“, ohne Ihre Klassen von einer zweiten Klasse erben zu müssen. Erweiterungsmethoden verhalten sich wie normale Methoden der Klasse:

class X : A, B { 
    public void MethodX() {...} 
    public void MethodY() {...} 
} 
public static void Main(string[] args) { 
    var x = new X(); 
    x.SomeMethodFromA(); 
    x.MethodX(); // Calls method from X 
    x.MethodY(); // Calls method from X 
    x.MethodZ(); // Calls method from ExtensionsB 
} 
+0

Das ist perfekt! Ich möchte, dass Sie das Attribut "class" in Ihrer Erweiterungsklasse hinzufügen. Und ich möchte darauf hinweisen, dass die Erweiterungsmethode innerhalb der Klasse mit this.Extension() aufgerufen werden kann. Der Aufruf von Extension() innerhalb der Klasse funktioniert nicht. –

1

Ich denke, Ihre beste Wette eine Instanz B im Konstruktor von A erfordern würde und dann aussetzen oder die Methoden der B rufen bei Bedarf:

public class X : A, C 
{ 
    private readonly B _b; 

    public X(B b) 
    { 
     _b = b; 
    } 
} 

Sie auf eine Vielzahl von Informationen finden wenn Sie diese Art von Ansatz aussehen Composition over inheritance

+0

Das würde den Entwickler dazu zwingen, B zu implementieren (deklarieren), aber ich möchte, dass der Entwickler selbst auswählen (implementieren) darf. Als wäre B eine Schnittstelle –

+0

Ich bin nicht wirklich sicher, was du meinst; Implementierung und Deklaration sind nicht dasselbe. Es ist vielleicht einfacher, eine Lösung zu empfehlen, wenn Sie ein konkretes Beispiel geben. Aber Komposition ist ein ziemlich flexibler Ansatz. – RagtimeWilly

+0

Es tut uns leid, dass Sie kein spezifisches Beispiel angegeben haben. Was ich meinte ist, dass dein X immer ein Feld von B deklariert. Aber ich möchte in der Lage sein zu entscheiden, ob mein X B verwendet (implementiert) oder nicht. Mit der Antwort von "dasblinkenlight" kann ich jetzt entscheiden, B auf mein X zu setzen oder es zu ignorieren. Wenn ich mich entscheide, es zu ignorieren, wird es kein Feld von B auf meinem X geben. –

Verwandte Themen