Ein Zitat aus C # in Kurzform.
Ein Problem, das mit einem Delegierten gelöst werden kann, kann auch mit einem gelöst werden
Schnittstelle. Im Folgenden wird beispielsweise erläutert, wie wir unser Filterproblem lösen können
Eine ITransformer
Schnittstelle:
Ein Delegiertenentwurf ist möglicherweise eine bessere Wahl als ein Schnittstellendesign, wenn einer oder mehrere von Diese Bedingungen sind wahr:
Im ITransformer-Beispiel brauchen wir kein Multicast. Allerdings die Schnittstelle definiert nur eine einzige Methode. Darüber hinaus muss unser Abonnent möglicherweise implementieren ITransformer mehrere Male, um verschiedene Transformationen, wie Quadrat oder Würfel zu unterstützen. Mit Schnittstellen müssen wir seit Test einen eigenen Typ pro Transformation schreiben kann ITtransformer nur einmal implementieren. Das ist ziemlich umständlich:
%Vor%Und hier ist der Code mit Delegat
%Vor%Eine Schnittstelle ist ein Vertrag - sie definiert Methoden und Eigenschaften, die jede implementierende Klasse haben muss, und daher weiß jeder Verbraucher der Schnittstelle, dass sie existieren und sie verwenden können.
Ein Delegat ist eine Rückrufseite - er definiert eine Methodensignatur, die jede Methode mit derselben Signatur aufrufen kann.
Siehe Delegierte und Schnittstellen zum C # -Programmierhandbuch.
Ein Beispiel für eine Schnittstelle ist die IEnumerable -Schnittstelle. Es hat nur ein Mitglied definiert - GetEnumerator
. Jedes Objekt, das diese Schnittstelle implementiert, verfügt über diese Methode und jeder Code, der ein solches Objekt verwendet, kann diese Methode aufrufen.
Ein Beispiel für einen Delegaten ist der Predicate<T>
Delegat. Es ist ein generischer Delegat, der wie folgt definiert ist:
Dies bedeutet, dass es jeden Typ T aufnimmt und ein bool
zurückgibt. Jede Methode, die einen einzelnen Typparameter akzeptiert und eine bool
zurückgibt, ist eine Übereinstimmung für diesen Delegaten und kann damit verwendet werden.
Da Delegaten auch Objekte sind, können sie an Funktionen übergeben werden. Jede Funktion, die einen Predicate<T>
-Delegaten hat, kann also in jedem mathod übergeben werden, der diesem entspricht. Viele der Linq-Operatoren verfügen über Delegaten als Parameter. Siehe Beispiele hier .
Eine Schnittstelle kann als funktionale Definition (oder Vertrag) betrachtet werden. In der realen Welt haben viele Objekte wohlbekannte Schnittstellen, die sie weitgehend (aber nicht vollständig) austauschbar machen.
Nehmen Sie zum Beispiel ein Auto. Sobald Sie lernen, wie man ein Auto fährt, lernen Sie die "Auto-Driving-Schnittstelle". Sie wissen, dass es eine Accelerate () - Funktion und eine Stop () - Funktion geben wird, und normalerweise eine ShiftGears () -Funktion (selbst wenn sie es nur aus dem Park herausnimmt und in das Laufwerk setzt). Es gibt auch eine Steer () - Funktion und eine SignalTurn () -Funktion.
Es gibt keine Garantie, dass eine bestimmte Implementierung auf die gleiche Weise funktioniert. Zum Beispiel kann ein Toyota eine "Stop ()" -Methode in seiner CarDriving-Schnittstelle haben, die tatsächlich Accelerate () aufruft.
Das Fahrzeug kann zusätzliche Schnittstellen wie die Sitzgurt-Schnittstelle oder die Funkschnittstelle unterstützen. Obwohl sich jede Implementierung dieser Objekte unterscheiden kann, gibt es immer eine Kernfunktionalität, die allen Typen dieser Objekte gemein ist. Dadurch können sie weitgehend austauschbar genutzt werden, ohne dass eine andere Schnittstelle neu gelernt werden muss.
Schnittstellen in C # sind ähnlich. Verschiedene Objektimplementierungen können dieselbe Schnittstellenimplementierung enthalten, und was sie tun, kann unterschiedlich sein, aber Sie können ein Objekt behandeln, das eine bestimmte Schnittstelle implementiert, genauso wie Sie ein anderes Objekt behandeln, das die gleiche Schnittstelle implementiert.
Wenn Sie verstehen, was die Ererbung ist, dann ist eine andere Möglichkeit, über Schnittstellen nachzudenken, dass sie dieselbe wie eine Klasse sind, aber sie haben keine Implementierung. Wenn also eine Klasse von einer anderen Klasse erbt, erbt sie sowohl die Klasse "interface" als auch die "Implementierung". Wenn eine Klasse nur eine Schnittstelle enthält, dann fehlt eine Implementierung und die neue Klasse muss diese Implementierung selbst erstellen.
Ein Delegierter, ist völlig anders. Ein Delegat ist (unter anderem) ein Funktionszeiger, der objektbewusst ist. Ein Funktionszeiger ist eine Variable, ähnlich wie andere Variablen, aber der Typ ist "delegate" anstatt "int" oder "string". Und anstatt Daten zu halten, enthält es einen Zeiger auf eine Methode (zusammen mit einigen Statusinformationen), so dass Sie verschiedene Funktionen zur Laufzeit dynamisch aufrufen können.
Im folgenden Code ist der Aufruf von "foo" behoben. Sie können nicht zur Laufzeit entscheiden, dass Sie stattdessen "bar" aufrufen möchten:
%Vor%Wenn Sie stattdessen etwas wie das Folgende getan haben, können Sie dann verschiedene Methoden als Argumente an Ihre Methode übergeben und sie dynisch aufrufen lassen:
%Vor%Delegierte können mehr als das tun, aber das ist eine grundlegende Art, an sie zu denken.
Okay, ich kann mit dir auf Englisch reden. Du bist menschlich. Ich kann mit jedem Menschen auf Englisch sprechen; Ich muss nicht alle Menschen auf der Erde wissen, um mit ihnen auf Englisch zu sprechen; Mir ist nur wichtig, dass sie Englisch sprechen.
OK, also ist ein Mensch ein Objekt. Englisch ist die Schnittstelle.
Viele Menschen implementieren die Schnittstelle IEnglish
!
Wenden Sie das jetzt in einem klassischen technischen Sinne an. Ich habe ein Auto und eine Autobatterie. Das Auto interessiert sich nicht für die Art der Batterie, wo sie hergestellt wurde oder welche Form sie hat. Die Batterie kümmert sich nicht um das Auto. Sie sind funktional abstrakt voneinander.
Die Batterie liefert Strom und implementiert die Schnittstelle IBattery
. Das Auto wird nur Objekte akzeptieren, die IBattery
implementieren (d. H. Physische Objekte, die Autobatterien sind !!)
Semantisch sind Schnittstellen und Delegierte weitgehend gleichwertig. Eine Schnittstelle definiert, was ein Objekt tut (Methoden und Eigenschaften) ... und ein Delegat definiert, was eine bestimmte Methode tut. Delegierte geben die Parameter einer Funktion oder Methode an .... sie sind typsichere Funktionszeiger. Ich muss mehr darüber nachdenken, um ein echtes Beispiel dafür zu finden.
Eine Schnittstelle ist eine Sammlung von Methoden, die an ein einzelnes Objekt gebunden sind. (Randnotiz: Objekte können mehrere Schnittstellen freilegen, so dass sie mehrere "Persönlichkeiten" aufweisen können.)
Ein Delegat ist eine Abstraktion eines einzelnen Methodenaufrufs. Der Aufruf eines Delegierten bewirkt, dass ein anderer Code aufgerufen wird, über den der Anrufer nichts weiß.
Eine etwas zu vereinfachte Ansicht von Dingen, die nichtsdestoweniger den Geschmack geben, ist, einen Delegierten als Spezialfall einer Schnittstelle mit genau einer Methode zu betrachten.
Tags und Links c#