Rückruf (Computerprogrammierung)

Im Computerprogrammierung, a zurückrufen oder Rückruffunktion ist ein Hinweis auf ausführbarer Code das ist als ein bestanden Streit zu einem anderen Code; Dieser Code wird erwartet zurückrufen (Ausführen) Die Rückruffunktion als Teil ihres Jobs. Diese Ausführung kann sofort wie in a sein synchroner Rückruf, oder es kann zu einem späteren Zeitpunkt passieren wie in einem Asynchroner Rückruf. Programmiersprachen Unterstützen Sie Rückrufe auf unterschiedliche Weise und implementieren sie häufig mit Unterroutinen, Lambda -Ausdrücke, Blöcke, oder Funktionszeiger.
Entwurf
Es gibt zwei Arten von Rückrufen, die sich in der Art und Weise unterscheiden, wie sie den Datenfluss zur Laufzeit steuern: Rückrufe blockieren (auch bekannt als synchrone Rückrufe oder nur Rückrufe) und Aufgeschobene Rückrufe (auch bekannt als Asynchrone Rückrufe). Während das Blockieren von Rückrufen aufgerufen wird, bevor eine Funktion zurückgibt (wie im C -Beispiel unten), können aufgeschobene Rückrufe nach Rückgabe einer Funktion aufgerufen werden. Aufgeschobene Rückrufe werden häufig im Kontext von E/A -Operationen oder Ereignisbehandlungen verwendet und von Interrupts oder einem anderen Thread bei mehreren Threads aufgerufen. Aufgrund ihrer Natur können das Blockieren von Rückrufen ohne Interrupts oder mehrere Threads funktionieren, was bedeutet, dass das Blockieren von Rückrufen nicht häufig zur Synchronisation oder zur Delegation von Arbeiten an einen anderen Thread verwendet werden.
Rückrufe werden verwendet, um Anwendungen in zu programmieren Fenstersysteme. In diesem Fall liefert die Anwendung (eine Referenz auf) eine bestimmte benutzerdefinierte Rückruffunktion für das Betriebssystem, mit dem diese anwendungsspezifische Funktion als Antwort auf Ereignisse wie Mausklicks oder Tastendrucke aufgerufen wird. Ein Hauptanliegen hier ist das Management von Privilegien und Sicherheit: Während die Funktion aus dem Betriebssystem aufgerufen wird, sollte sie nicht mit demselben ausgeführt werden Privileg als System. Eine Lösung für dieses Problem ist die Verwendung Ringe des Schutzes.
Implementierung
Die Form eines Rückrufs variiert zwischen Programmiersprachen:
- Im Montage, C, C ++, Pascal, Modula2 und ähnliche Sprachen, eine Maschinenebene Zeiger Eine Funktion kann als Argument an eine andere (interne oder externe) Funktion übergeben werden. Dies wird von den meisten Compilern unterstützt und bietet den Vorteil, verschiedene Sprachen ohne spezielle Wrapper -Bibliotheken oder -Kassen zusammenzusetzen. Ein Beispiel kann das sein Windows -API Das ist direkt (mehr oder weniger) von vielen verschiedenen Sprachen, Compilern und Abgängern zugänglich.
- Mit C ++ ermöglicht Objekte ihre eigene Implementierung des Funktionsaufrufvorgangs. Das Standard -Vorlagenbibliothek Akzeptiert diese Objekte (genannt Funkern) sowie Funktionszeiger als Parameter für verschiedene polymorphe Algorithmen.
- Viele Dynamische Sprachen, wie zum Beispiel JavaScript, Lua, Python, Perl[1][2] und PhpLassen Sie einfach ein Funktionsobjekt übergeben.
- CLI -Sprachen wie zum Beispiel C# und Vb.net zur Verfügung stellen Typ-Safe Einkapselung der Referenz, a "delegieren", um gut zu definieren Funktionszeiger. Diese können als Rückrufe verwendet werden.
- Ereignisse und Event -HandlerGeben Sie wie in .NET -Sprachen verallgemeinerte Syntax für Rückrufe an.
- Funktionssprachen unterstützen im Allgemeinen im Allgemeinen erstklassige Funktionen, die als Rückrufe an andere Funktionen übergeben, als Daten gespeichert oder aus Funktionen zurückgegeben werden.
- Einige Sprachen, wie z. Algol 68, Perl, Python, Rubin, Smalltalk, C ++ 11 Und später ermöglichen neuere Versionen von C# und VB.NET sowie die meisten funktionalen Sprachen unbenannte Codeblöcke (Lambda -Ausdrücke) anstelle von Verweise auf Funktionen an anderer Stelle geliefert werden.
- In einigen Sprachen, z. Planen, Ml, JavaScript, Perl, Python, SmallTalk, PHP (seit 5.3.0),[3] C ++ 11 und später Java (seit 8),[4] und viele andere, solche Funktionen können sein Schließungen, d. H. Sie können auf Variablen zugreifen und ändern, die lokal im Kontext definiert wurden, in dem die Funktion definiert wurde. Beachten Sie, dass Java die lokalen Variablen jedoch im umschließenden Bereich nicht ändern kann.
- Im Objekt orientierte Programmierung Sprachen ohne funktionsbewertete Argumente wie in Java Vor seiner 8 -Version können Rückrufe simuliert werden, indem eine Instanz einer abstrakten Klasse oder Schnittstelle bestanden wird, von der der Empfänger eine oder mehrere Methoden aufruft, während das aufrufende Ende eine konkrete Implementierung bietet. Solche Objekte sind effektiv ein Bündel Rückrufe sowie die Daten, die sie manipulieren müssen[Klarstellung erforderlich]. Sie sind nützlich bei der Implementierung verschiedener Designmuster wie zum Beispiel Besucher, Beobachter, und Strategie.
Verwenden
C
Rückrufe haben eine Vielzahl von Verwendungen, beispielsweise in Fehlersignalisierung: a Unix Das Programm möchte möglicherweise nicht sofort enden, wenn es erhält SigtermUm sicherzustellen, dass die Kündigung ordnungsgemäß behandelt wird, wird die Reinigungsfunktion als Rückruf registriert. Rückrufe können auch verwendet werden, um zu steuern, ob eine Funktion wirkt oder nicht: Xlib Ermöglicht benutzerdefinierte Prädikate, festzustellen, ob ein Programm ein Ereignis verarbeiten möchte.
Folgende C Der Code zeigt die Verwendung von Rückrufen zum Anzeigen von zwei Nummern.
#enthalten #enthalten #enthalten /* Die Aufruffunktion nimmt einen einzelnen Rückruf als Parameter ab. */ Leere Printtwonumbers(int (*numbersource) (Leere)) { int Val1 = numbersource(); int Val2 = numbersource(); printf(" %d und %d\n", Val1, Val2); } / * Ein möglicher Rückruf */ int über neuntausend(Leere) { Rückkehr (Rand()%1000) + 9001; } /* Ein weiterer möglicher Rückruf. */ int Sinn des Lebens(Leere) { Rückkehr 42; } /* Hier nennen wir PrintTwonumbers () mit drei verschiedenen Rückern. */ int hauptsächlich(Leere) { time_t t; Srand((ohne Vorzeichen)Zeit(&t)); // Init Seed für die zufällige Funktion Printtwonumbers(&Rand); Printtwonumbers(&über neuntausend); Printtwonumbers(&Sinn des Lebens); Rückkehr 0; }
Beispielausgabe:
13602 und 26331 9235 und 9044 42 und 42
Beachten Sie, wie sich dies vom einfacher Übergeben der Ausgabe der Rückruffunktion an die Aufruffunktion unterscheidet, PrintTwonumbers () - anstatt denselben Wert zweimal zu drucken, ruft die PrintTwonumbers den Rückruf so oft auf, wie er erforderlich ist. Dies ist einer der beiden Hauptvorteile von Rückrufen.
Der andere Vorteil ist, dass die Aufruffunktion alle Parameter übergeben kann, die sie wünscht, an die aufgerufenen Funktionen (nicht im obigen Beispiel angezeigt). Dies ermöglicht korrekt Informationen verstecken sich: Der Code, der einen Rückruf an eine Aufruffunktion übergibt, muss die Parameterwerte, die an die Funktion übergeben werden, nicht kennen. Wenn es nur den Rückgabewert überschritten hat, müssten die Parameter öffentlich freigelegt werden.[Beispiel erforderlich]
Ein anderes Beispiel:
/* * Dies ist ein einfaches C -Programm, mit dem die Verwendung von Rückrufen nach demonstrieren kann * Die Rückruffunktion befindet sich in derselben Datei wie der aufrufende Code. * Die Rückruffunktion kann später in die externe Bibliothek eingesetzt werden * z.B. ein gemeinsames Objekt, um die Flexibilität zu erhöhen. * */ #enthalten #enthalten Typedef Struktur _Mymsg { int Appid; verkohlen msgbody[32]; } Mymmsg; Leere myfunc(Mymmsg *Nachricht) { wenn (Strlen(Nachricht->msgbody) > 0 ) printf("App id = %d \nMsg = %s \n",Nachricht->Appid, Nachricht->msgbody); anders printf("App id = %d \nMsg = keine msg\n",Nachricht->Appid); } /* * Prototyperklärung */ Leere (*zurückrufen) (Mymmsg *); int hauptsächlich(Leere) { Mymmsg MSG1; MSG1.Appid = 100; Strcpy(MSG1.msgbody, "Das ist ein Test\n"); /* * Weisen Sie der Funktion die Adresse der Funktion "myfunc" zu * Zeiger "Rückruf" (kann auch als "callback = & myfunc" geschrieben werden;) */ zurückrufen = myfunc; /* * Rufen Sie die Funktion auf (kann auch als "(* Rückruf) (& msg1) geschrieben werden;") */ zurückrufen(&MSG1); Rückkehr 0; }
Die Ausgabe nach Zusammenstellung:
$ GCC CBTEST.C$ ./a.outApp id = 100 Msg = Dies ist ein Test
Diese Informationen verstecken bedeutet, dass Rückrufe bei der Kommunikation zwischen Prozessen oder Threads oder durch serialisierte Kommunikation und tabellarische Daten verwendet werden können.[Klarstellung erforderlich]
In C ++, Functor wird auch üblicherweise neben der Verwendung des Funktionszeigers in C verwendet.
C#
Ein einfacher Rückruf in C#:
Öffentlichkeit Klasse Klasse 1 { statisch Leere Hauptsächlich(Saite[] Args) { Klasse 2 C2 = Neu Klasse 2(); /* * Aufrufen der Methode auf der Klasse2 mit Rückrufmethode als Parameter */ C2.Methode(CallbackMethod); } /* * Die Rückrufmethode. Diese Methode druckt die Zeichenfolge, die im Rückruf gesendet wurde */ statisch Leere CallbackMethod(Saite str) { Konsole.Schreiben($ "Rückruf war: {Str}"); } } Öffentlichkeit Klasse Klasse 2 { /* * Die Methode, die zum Anrufer zurückruft. Ergreifen Sie eine Aktion (Methode) als Parameter */ Öffentlichkeit Leere Methode(Aktion<Saite> zurückrufen) { /* * Ruft mit der angegebenen Nachricht zu Method Callbackmet in Klasse1 zurück */ zurückrufen("Die Nachricht zum Rücksenden"); } }
JavaScript
Rückrufe werden bei der Implementierung von Sprachen verwendet, wie z. JavaScript, einschließlich der Unterstützung von JavaScript-Funktionen als Rückrufe über JS-CTYPES[5] und in Komponenten wie AddEventListener.[6] Ein nationales Beispiel eines Rückrufs kann jedoch ohne komplexen Code geschrieben werden:
Funktion Berechnung(Num1, Num2, Callbackfunktion) { Rückkehr Callbackfunktion(Num1, Num2); } Funktion CALCPRODUCT(Num1, Num2) { Rückkehr Num1 * Num2; } Funktion Berechnung(Num1, Num2) { Rückkehr Num1 + Num2; } // Alarms 75, das Produkt von 5 und 15 Alarm(Berechnung(5, 15, CALCPRODUCT)); // alarmiert 20, die Summe von 5 und 15 Alarm(Berechnung(5, 15, Berechnung));
Zuerst eine Funktion Berechnung ist mit einem Parameter definiert, der für einen Rückruf bestimmt ist: Callbackfunktion. Dann eine Funktion, die als Rückruf zu verwendet werden kann Berechnung ist definiert, CALCPRODUCT. Andere Funktionen können für verwendet werden Callbackfunktion, wie Berechnung. In diesem Beispiel, Berechnung() wird zweimal angerufen, einmal mit CALCPRODUCT als Rückruf und einmal mit Berechnung. Die Funktionen geben das Produkt und die Summe zurück, und dann wird die Warnung auf dem Bildschirm angezeigt.
In diesem primitiven Beispiel ist die Verwendung eines Rückrufs in erster Linie eine Demonstration des Prinzips. Man könnte die Rückrufe einfach als reguläre Funktionen anrufen, CalcProduct (Num1, Num2). Rückrufe werden im Allgemeinen verwendet, wenn die Funktion Ereignisse ausführen muss Asynchrone JavaScript (basierend auf Timern) oder Xmlhttprequest Anfragen. Nützliche Beispiele finden Sie in JavaScript -Bibliotheken wie zum Beispiel JQuery wobei die .each () -Methode über ein Array-ähnliches Objekt iteriert, wobei das erste Argument ein Rückruf ist, der bei jeder Iteration durchgeführt wird.
Rot und Rebol
Von dem JavaScript Oben hier ist, wie man dasselbe in beiden implementieren würde Rebol oder Rot (Programmiersprache). Beachten Sie die sauberere Präsentation von Daten als Code.
- Rückgabe ist impliziert, da der Code in jeder Funktion die letzte Zeile des Blocks ist
- Als Alarm ist eine Zeichenfolge erforderlich, erzeugt die Form eine Zeichenfolge aus dem Ergebnis der Berechnung
- Das Getwort! Werte (d. H.: Calc-Produkt und: Calc-Sum) auslösen den Interpreter, um den Code der Funktion zurückzugeben, anstatt mit der Funktion zu bewerten.
- Der Datentyp! Referenzen in einem Block! [schweben! Ganzzahl!] Beschränken Sie die Art der als Argumente übergebenen Werte.
Rot [Titel: "Callback -Beispiel"] Berechnung: Func [ Num1 [Nummer!] Num2 [Nummer!] Rückruffunktion [Funktion!] ][ Rückruffunktion Num1 Num2 ] Kalkprodukt: Func [ Num1 [Nummer!] Num2 [Nummer!] ][ Num1 * Num2 ] Berechnung: Func [ Num1 [Nummer!] Num2 [Nummer!] ][ Num1 + Num2 ] ; Warnungen 75, das Produkt von 5 und 15 Alarm bilden Berechnung 5 15 : Kalkprodukt ; Warnungen 20, die Summe von 5 und 15 Alarm bilden Berechnung 5 15 : Berechnung
Lua
Ein Farb -Tweening -Beispiel mit dem Roblox Engine, der einen optionalen .doner -Rückruf benötigt:
Warten(1) lokal Dt = Warten() Funktion Tween_Color(Objekt, Finish_Color, FADE_TIME) lokal STEP_R = Finish_Color.r - Objekt.BackgroundColor3.r lokal STEP_G = Finish_Color.g - Objekt.BackgroundColor3.g lokal STEP_B = Finish_Color.b - Objekt.BackgroundColor3.b lokal Total_Steps = 1/(Dt*(1/FADE_TIME)) lokal abgeschlossen; coroutine.wrap(Funktion() zum i = 0, 1, Dt*(1 / FADE_TIME) tun Objekt.BackgroundColor3 = Color3.Neu ( Objekt.BackgroundColor3.r + (STEP_R/Total_Steps), Objekt.BackgroundColor3.g + (STEP_G/Total_Steps), Objekt.BackgroundColor3.b + (STEP_B/Total_Steps) ) Warten() Ende wenn abgeschlossen dann abgeschlossen() Ende Ende) ()) Rückkehr { erledigt = Funktion(zurückrufen) abgeschlossen = zurückrufen Ende } Ende Tween_Color(SONDER_OBJECT, Color3.Neu(1, 0, 0), 1).erledigt(Funktion() drucken "Farbe Tweening fertig!" Ende)
Python
Eine typische Verwendung von Rückrufen in Python (und anderen Sprachen) besteht darin, UI -Elementen Ereignisse zuzuweisen.
Hier ist ein sehr triviales Beispiel für die Verwendung eines Rückrufs in Python. Definieren Sie zuerst zwei Funktionen, den Rückruf und den Anrufcode, und geben Sie die Rückruffunktion in den aufrufenden Code ein.
>>> def get_square(val): ... "" Der Rückruf. "" "" ... Rückkehr val ** 2 ... >>> def Anrufer(Func, val): ... Rückkehr Func(val) ... >>> Anrufer(get_square, 5) 25
Julia
Funktionen in Julia sind erstklassiger BürgerSie können einfach an übergeordnete Funktionen übergeben werden, um sie innerhalb des Körpers dieser Funktionen zu verwenden (genannt).
Hier das gleiche Beispiel oben in Julia:
Julia> get_square(val) = val^2 # Der Rückruf get_square (generische Funktion mit 1 Methode) Julia> Anrufer(Func,val) = Func(val) Anrufer (Generische Funktion mit 1 Methode) Julia> Anrufer(get_square,5) 25
Siehe auch
- Befehlsmuster
- Fortsetzungsstil
- Ereignisschleife
- Ereignisgesteuerte Programmierung
- Implizite Berufung
- Kontrollinversion
- libSsigc ++, eine Rückrufbibliothek für C ++
- Signale und Slots
- Benutzerbeenden
Verweise
- ^ "Perl -Kochbuch - 11.4. Verweise auf Funktionen nehmen". Abgerufen 2008-03-03.
- ^ "Advanced Perl -Programmierung - 4.2 Verwenden von Subroutine -Referenzen". Abgerufen 2008-03-03.
- ^ "PHP -Sprachreferenz - Anonyme Funktionen". Abgerufen 2011-06-08.
- ^ "Was ist neu in JDK 8". Oracle.com.
- ^ Holley, Bobby; Shepherd, Eric (Hrsg.). "Rückrufe deklarieren und verwenden". Dokumente. Mozilla Developer Network (Dokumentationsseite). Archiviert vom Original am 2019-01-17. Abgerufen 2021-12-16.
- ^ "Erstellen von JavaScript -Rückrufen in Komponenten". Archiv. UDN Web Docs (Dokumentationsseite). Sek. JavaScript fungiert als Rückrufe. Archiviert vom Original am 2021-12-16. Abgerufen 2021-12-16.
Externe Links
- Grundlegende Instinkte: Implementierung von Rückrufbenachrichtigungen mithilfe von Delegierten
- Implementieren Sie Rückrufroutinen in Java
- Implementieren Sie das Skript -Rückruf -Framework in ASP.NET
- Schnittstelle C ++ - Mitgliedsfunktionen mit C -Bibliotheken (Archiviert vom Original am 6. Juli 2011)
- Stilstudie Nr. 2: Generische Rückrufe