Wann wird die Verkettung verwendet?
Funktionsverkettung ist vor allem in Sprachen beliebt, in denen eine IDE mit automatischer Vervollständigung üblich ist. Beispielsweise verwenden fast alle C # -Entwickler Visual Studio. Wenn Sie mit C # entwickeln, kann das Hinzufügen von Verkettungen zu Ihren Methoden für Benutzer dieser Klasse Zeit sparen, da Visual Studio Sie beim Erstellen der Kette unterstützt.
Auf der anderen Seite werden Sprachen wie PHP, die von Natur aus sehr dynamisch sind und in IDEs häufig keine automatische Vervollständigung unterstützen, weniger Klassen sehen, die die Verkettung unterstützen. Eine Verkettung ist nur dann angebracht, wenn korrekte phpDocs verwendet werden, um die verkettbaren Methoden freizulegen.
Was ist Verkettung?
Bei einer Klasse mit dem Namen sind Foo
die folgenden beiden Methoden verkettbar.
function what() { return this; }
function when() { return new Foo(this); }
Die Tatsache, dass man auf die aktuelle Instanz verweist und eine neue Instanz erstellt, ändert nichts daran, dass es sich um verkettbare Methoden handelt.
Es gibt keine Goldregel, dass eine verkettbare Methode nur auf das aktuelle Objekt verweisen darf. Tatsächlich können verkettbare Methoden zwei verschiedene Klassen umfassen. Beispielsweise;
class B { function When() { return true; } };
class A { function What() { return new B(); } };
var a = new A();
var x = a.What().When();
this
In keinem der obigen Beispiele wird darauf verwiesen . Der Code a.What().When()
ist ein Beispiel für eine Verkettung. Interessant ist, dass der Klassentyp B
niemals einer Variablen zugewiesen wird.
Eine Methode wird verkettet, wenn ihr Rückgabewert als nächste Komponente eines Ausdrucks verwendet wird.
Hier sind einige weitere Beispiele
// return value never assigned.
myFile.Open("something.txt").Write("stuff").Close();
// two chains used in expression
int x = a.X().Y() * b.X().Y();
// a chain that creates new strings
string name = str.Substring(1,10).Trim().ToUpperCase();
Wann zu verwenden this
undnew(this)
Zeichenfolgen in den meisten Sprachen sind unveränderlich. Verkettungsmethodenaufrufe führen also immer dazu, dass neue Zeichenfolgen erstellt werden. Wobei als Objekt wie StringBuilder geändert werden kann.
Konsistenz ist eine bewährte Methode.
Wenn Sie Methoden haben, die den Status eines Objekts ändern und zurückgeben this
, mischen Sie keine Methoden ein, die neue Instanzen zurückgeben. Erstellen Sie stattdessen eine bestimmte Methode mit dem Namen Clone()
, die dies explizit ausführt.
var x = a.Foo().Boo().Clone().Foo();
Das ist viel klarer, was im Inneren vor sich geht a
.
Der Schritt nach draußen und zurück Trick
Ich nenne dies den Step-out- und Back- Trick, weil er viele häufige Probleme im Zusammenhang mit der Verkettung löst. Dies bedeutet im Grunde, dass Sie aus der ursprünglichen Klasse in eine neue temporäre Klasse und dann zurück in die ursprüngliche Klasse wechseln.
Die temporäre Klasse existiert nur, um der ursprünglichen Klasse spezielle Funktionen bereitzustellen, jedoch nur unter besonderen Bedingungen.
Es gibt oft Zeiten, in denen eine Kette den Status ändern muss , aber die Klasse A
kann nicht alle diese möglichen Zustände darstellen . Während einer Kette wird eine neue Klasse eingeführt, die einen Verweis auf enthält A
. Dies ermöglicht es dem Programmierer, in einen Zustand und zurück zu wechseln A
.
Hier ist mein Beispiel, lassen Sie den Sonderzustand bekannt sein als B
.
class A {
function Foo() { return this; }
function Boo() { return this; }
function Change() return new B(this); }
}
class B {
var _a;
function (A) { _a = A; }
function What() { return this; }
function When() { return this; }
function End() { return _a; }
}
var a = new A();
a.Foo().Change().What().When().End().Boo();
Das ist ein sehr einfaches Beispiel. Wenn Sie mehr Kontrolle haben möchten, B
können Sie zu einem neuen Supertyp zurückkehren A
, der andere Methoden hat.
return this
. Wie kann ich den Benutzern meiner Bibliotheken helfen, mit dieser Situation umzugehen und sie zu verstehen? (Es wäre wirklich in Ordnung, ihnen zu erlauben, Methoden zu verketten, auch wenn dies nicht erforderlich ist. Oder sollte ich mich nur an einen Weg halten und überhaupt Änderungen vornehmen?)Abhängig von der Sprache ist es nicht idiomatisch , Methoden zu haben, die ihre Instanz oder Parameter zurückgeben
void
/unit
und ändern. Selbst in Sprachen, die dies früher mehr taten (C #, C ++), gerät es mit der Verlagerung hin zu einer funktionaleren Stilprogrammierung (unveränderliche Objekte, reine Funktionen) aus der Mode. Aber nehmen wir an, es gibt einen guten Grund für jetzt.Für bestimmte Verhaltensweisen (denken Sie
x++
) wird erwartet, dass die Operation das Ergebnis zurückgibt, obwohl sie die Variable ändert. Aber das ist größtenteils der einzige Grund, es selbst zu tun.Es hängt davon ab, ob.
In Sprachen, in denen copy / new und return üblich sind (C # LINQ und Strings), wäre die Rückgabe derselben Referenz verwirrend. In Sprachen, in denen Änderungen und Rückgaben üblich sind (einige C ++ - Bibliotheken), wäre das Kopieren verwirrend.
Die Signatur eindeutig zu machen (durch Rückgabe
void
oder Verwendung von Sprachkonstrukten wie Eigenschaften), wäre der beste Weg, dies zu klären. Danach ist es gut, den Namen klarSetFoo
zu machen, um zu zeigen, dass Sie die vorhandene Instanz ändern. Der Schlüssel ist jedoch, die Redewendungen der Sprache / Bibliothek beizubehalten, mit der Sie arbeiten.quelle
Clear()
oderAdd()
eines beliebigen Sammlungstyps dieselbe Instanz und geben sie zurückvoid
. In beiden Fällen sagen Sie, es wäre verwirrend ...obj = myCollection.Where(x => x.MyProperty > 0).OrderBy(x => x.MyProperty);
dann tun ?Where()
Gibt ein neues Sammlungsobjekt zurück.OrderBy()
gibt sogar ein anderes Sammlungsobjekt zurück, da der Inhalt sortiert ist.IEnumerable
, aber klar sein, sie sind keine Kopien, und sie sind nicht Sammlungen ( mit AusnahmeToList
,ToArray
usw.).ICollection
. Mein Fehler.(Ich habe C ++ als Ihre Programmiersprache angenommen)
Für mich ist dies hauptsächlich ein Aspekt der Lesbarkeit. Wenn A, B, C Modifikatoren sind, insbesondere wenn dies ein temporäres Objekt ist, das als Parameter an eine Funktion übergeben wird, z
verglichen mit
Wenn es in Ordnung ist, einen Verweis auf die geänderte Instanz zurückzugeben, würde ich ja sagen und Sie beispielsweise auf die Stream-Operatoren '>>' und '<<' verweisen ( http://www.cprogramming.com/tutorial/). operator_overloading.html )
quelle
Sie können die Methode auch mit der Kopierrückgabe verketten, anstatt die Rückgabe zu ändern.
Ein gutes C # -Beispiel ist string.Replace (a, b), das die Zeichenfolge, für die es aufgerufen wurde, nicht ändert, sondern stattdessen eine neue Zeichenfolge zurückgibt, mit der Sie fröhlich verketten können.
quelle