Callback ( engelsk call - call, English back - reverse) eller callback-funktion i programmering - skickar den körbara koden som en av parametrarna för en annan kod. Återuppringningen tillåter funktionen att exekvera koden som anges i argumenten när den anropas. Denna kod kan vara definierad i andra kodsammanhang och inte vara direkt anropbar från denna funktion. Vissa algoritmiska uppgifter har som ingång inte bara siffror eller objekt, utan också åtgärder (algoritmer), som naturligt anges som återuppringningar.
Callback-konceptet har många tillämpningar. Till exempel har vissa algoritmer (funktioner) som deluppgift uppgiften att beräkna ett hashvärde från en sträng. I argumenten när du startar algoritmen (funktionen) är det praktiskt att ange vilken funktion som ska användas för att beräkna hashvärdena.
Ett annat exempel på en algoritm för vilken det är naturligt att skicka en funktion som ett argument är en algoritm för att korsa något objektlager, applicera någon åtgärd på varje objekt. En återuppringning kan fungera som denna åtgärd (algoritm).
Callback-programmeringstekniken i programmeringsspråk som C är enkel. När huvudfunktionen anropas skickas den helt enkelt en pekare till återuppringningsfunktionen. Det klassiska exemplet är en funktion qsortfrån stdlib-biblioteket . Denna funktion sorterar en array av byteblock av samma längd. Som argument får den adressen till det första elementet i arrayen, antalet block i arrayen, storleken på blocket med byte och en pekare till en funktion för att jämföra två block av byte. Den här jämförelsefunktionen är återuppringningsfunktionen i det här exemplet:
#include <stdlib.h> // funktion för att jämföra heltal modulo int compare_abs ( const void * a , const void * b ) { int a1 = * ( int * ) a ; int b1 = * ( int * ) b ; return abs ( a1 ) - abs ( b1 ); } int main () { int storlek = 10 ; int m [ storlek ] = { 1 , -3 , 5 , -100 , 7 , 33 , 44 , 67 , -4 , 0 }; // sortering array m i stigande moduler qsort ( m , storlek , sizeof ( int ), compare_abs ); returnera 0 ; }Du kan tänka på en återuppringning som en åtgärd som skickas som ett argument till någon huvudprocedur. Och denna åtgärd kan ses som:
Exemplet som visas ovan motsvarar exakt det första fallet. Fallet där återuppringningen används som en "telefonanslutning" återspeglar koden där funktionen för att hantera en viss signal ges:
#include <stdio.h> #include <signal.h> flyktig sig_atomic_t br = 1 ; void sig ( int signum ) { br = 0 ; } int main ( int argc , char * argv []) { signal ( SIGINT , sig ); printf ( "Tryck på tangentkombinationen paus för att stoppa programmet \n " ); medan ( br ); printf ( "Mottog SIGINT, avsluta \n " ); returnera 0 ; }I vissa programmeringsspråk, som Common Lisp , Erlang , Scheme , Clojure , PHP , JavaScript , Perl , Python , Ruby och andra, är det möjligt att konstruera anonyma (onamngivna) funktioner och stängningsfunktioner direkt i huvudfunktionsanropsuttrycket, och denna möjlighet används i stor utsträckning.
I AJAX-teknik , när du gör en asynkron förfrågan till servern, måste du ange en återuppringningsfunktion som kommer att anropas så snart svaret på förfrågan kommer. Ofta definieras denna funktion "på plats" utan att ge den något specifikt namn:
nya Ajax . Request ( 'http://example.com/do_it' , { method : 'post' , onSuccess : function ( transport ) { // funktion anropad av fönster . alert ( "Klart!" ); // om begäran lyckades } , // onFailure : function () { // funktion anropad av fönster . alert ( "Fel!" ); // exekveringsfel vid begäran } });Återuppringningsfunktionen används också i Observers designmönster . Så, till exempel, med hjälp av Prototype- biblioteket kan du skapa en "observatör" som övervakar klick på ett element med en identifierare och, när en händelse tas emot, skriver ett meddelande inuti elementet : "my_button""message_box"
händelse . observe ( $ ( "my_button" ), 'click' , function () { $ ( "message_box" ). innerHTML = "Du klickade på knappen!" });Återuppringningsfunktionen är ett alternativ till funktionspolymorfism , nämligen den låter dig skapa funktioner med ett mer generellt syfte, istället för att skapa en serie funktioner som är lika strukturerade, men som bara skiljer sig på vissa ställen i de körbara deluppgifterna. Funktioner som tar andra funktioner som argument eller returnerar funktioner som ett resultat kallas funktioner av högre ordning . Callback-tekniken spelar en viktig roll för att uppnå kodåteranvändning .
För att bättre förstå orsakerna till att använda en återuppringning, överväg den enkla uppgiften att utföra följande operationer på en lista med siffror: skriv ut alla siffror, kvadrera alla siffror, öka alla siffror med 1, ställ in alla element till noll. Det är tydligt att algoritmerna för att utföra dessa fyra operationer är likartade - det här är en slinga som går förbi alla element i listan med någon åtgärd i slingkroppen, applicerad på varje element. Detta är en enkel kod, och i princip kan du skriva den 4 gånger. Men låt oss överväga ett mer komplicerat fall, när listan inte är lagrad i minnet, utan på disk, och flera processer kan arbeta med listan samtidigt och det är nödvändigt att lösa problemen med att synkronisera åtkomst till element (flera processer kan utföra olika uppgifter - ta bort vissa element från listan, lägga till nya, ändra befintliga objekt i listan). I det här fallet kommer uppgiften att gå igenom alla element i listan vara ganska komplex kod som man inte skulle vilja kopiera flera gånger. Det skulle vara mer korrekt att skapa en allmän funktion för att gå igenom elementen i listan och tillåta programmerare att abstrahera från hur övergångsalgoritmen fungerar och endast skriva en återuppringningsfunktion för att bearbeta ett enda element i listan.
Att strukturera mjukvara genom återuppringningsfunktioner är ett mycket bekvämt och allmänt använt tillvägagångssätt, eftersom beteendet hos ett program med oförändrad (inklusive stängd) kod kan ändras inom ett mycket brett spektrum. Detta implementeras på två sätt - antingen genom "alternativ implementering" av en funktion, eller genom att "lägga till ytterligare en funktion i anropskedjan".
Som regel implementerar utvecklaren inte all funktionalitet i programmet genom återuppringningar, utan bara det som är tänkt att utökas eller modifieras av plugins . För att ansluta plugins tillhandahålls en speciell procedur, som ersätter "standard" inversa funktioner från utvecklaren med alternativa från plugin.
Det mest kända exemplet på detta tillvägagångssätt är Microsoft Windows- operativsystemet , där återuppringningsfunktioner kallas "hanterare" ("hanterare"), och det är möjligt att infoga en ytterligare procedur mellan två standardiserade. Det här tillvägagångssättet kallas "händelseavlyssning" och används till exempel: av antivirus för att kontrollera filer som nås; virus för att läsa tecken inmatade från tangentbordet; nätverksfilter för att samla in statistik och blockera paket.
I moderna Unix- och Linux- system är det möjligt att dynamiskt ladda och ladda ur kärnmoduler, som också är baserade på callback-funktioner. Samtidigt finns det en modul (kärntillägg) FUSE , som i sin tur ger möjlighet för vanliga användarprogram att betjäna (avlyssna) förfrågningar till virtuella filsystem.
I mjukvara sker ibland en nedbrytning av program som helt bygger på callback-funktioner, vilket försämrar kodens läsbarhet något, men ger maximala möjligheter till plugins. Ett exempel på en sådan produkt är DokuWiki .
Fördelar:
Brister: