Callback (programmering)

Den aktuelle version af siden er endnu ikke blevet gennemgået af erfarne bidragydere og kan afvige væsentligt fra den version , der blev gennemgået den 21. januar 2021; checks kræver 3 redigeringer .

Callback ( engelsk  call  - call, English  back  - reverse) eller tilbagekaldsfunktion i programmering  - videregivelse af den eksekverbare kode som en af ​​parametrene for en anden kode. Tilbagekaldet tillader funktionen at udføre den kode, der er angivet i argumenterne, når den kaldes. Denne kode kan være defineret i andre kodekontekster og kan ikke direkte kaldes fra denne funktion. Nogle algoritmiske opgaver har som input ikke kun tal eller objekter, men også handlinger (algoritmer), som naturligt angives som tilbagekald.

Ansøgning

Callback-konceptet har mange anvendelsesmuligheder. For eksempel har nogle algoritmer (funktioner) som underopgave til opgave at beregne en hashværdi ud fra en streng. I argumenterne ved start af algoritmen (funktionen) er det praktisk at angive, hvilken funktion der skal bruges til at beregne hashværdierne.

Et andet eksempel på en algoritme, for hvilken det er naturligt at sende en funktion som et argument, er en algoritme til at krydse et eller andet objektlager og anvende en handling på hvert objekt. Et tilbagekald kan fungere som denne handling (algoritme).

Callback-programmeringsteknikken i programmeringssprog som C er enkel. Når hovedfunktionen kaldes, sendes den blot en pointer til tilbagekaldsfunktionen. Det klassiske eksempel er en funktion qsortfra stdlib-biblioteket . Denne funktion sorterer et array af byteblokke af samme længde. Som argumenter modtager den adressen på det første element i arrayet, antallet af blokke i arrayet, størrelsen af ​​blokken af ​​bytes og en pointer til en funktion til at sammenligne to blokke af bytes. Denne sammenligningsfunktion er tilbagekaldsfunktionen i dette eksempel:

#include <stdlib.h> // funktion til at sammenligne heltal modulo int compare_abs ( const void * a , const void * b ) { int a1 = * ( int * ) a ; int b1 = * ( int * ) b ; returnere abs ( a1 ) - abs ( b1 ); } int main () { int størrelse = 10 ; int m [ størrelse ] = { 1 , -3 , 5 , -100 , 7 , 33 , 44 , 67 , -4 , 0 }; // sortering array m i stigende moduler qsort ( m , size , sizeof ( int ), compare_abs ); returnere 0 ; }

Du kan tænke på et tilbagekald som en handling, der er sendt som et argument til en eller anden hovedprocedure. Og denne handling kan ses som:

  • underopgave og bruges til at behandle data inden for denne procedure;
  • "Telefonforbindelse" bruges til at "kontakte" med den, der ringede til proceduren, når en hændelse indtræffer ( engelsk  tilbagekald oversættes bogstaveligt som "ring tilbage").

Eksemplet ovenfor svarer nøjagtigt til det første tilfælde. Det tilfælde, hvor tilbagekaldet bruges som en "telefonforbindelse" afspejler koden, hvor funktionen til at håndtere et bestemt signal er givet:

#include <stdio.h> #include <signal.h> flygtig sig_atomic_t br = 1 ; void sig ( int signum ) { br = 0 ; } int main ( int argc , char * argv []) { signal ( SIGINT , sig ); printf ( "Tryk på pause tastaturkombination for at stoppe programmet \n " ); mens ( br ); printf ( "Modtaget SIGINT, afslut \n " ); returnere 0 ; }

I nogle programmeringssprog, såsom Common Lisp , Erlang , Scheme , Clojure , PHP , JavaScript , Perl , Python , Ruby og andre, er det muligt at konstruere anonyme (unavngivne) funktioner og lukkefunktioner direkte i hovedfunktionskaldsudtrykket, og denne mulighed er meget brugt.

I AJAX-teknologi skal du, når du laver en asynkron anmodning til serveren, angive en tilbagekaldsfunktion, der vil blive kaldt, så snart svaret på anmodningen ankommer. Ofte er denne funktion defineret "på plads" uden at give den noget specifikt navn:

nye Ajax . Request ( 'http://example.com/do_it' , { method : 'post' , onSuccess : function ( transport ) { // funktion kaldet af vinduet . alert ( "Udført!" ); // hvis anmodningen var vellykket } , // onFailure : function () { // funktion kaldet af vinduet . alarm ( "Fejl!" ); // på anmodning udførelsesfejl } });

Callback-funktionen bruges også i Observer - designmønsteret . Så ved at bruge Prototype- biblioteket kan du for eksempel oprette en "observator", der overvåger klik på et element med en identifikator , og når en hændelse modtages, skriver en besked inde i elementet : "my_button""message_box"

begivenhed . observe ( $ ( "my_button" ), 'klik' , function () { $ ( "message_box" ). innerHTML = "Du klikkede på knappen!" });

Callback-funktionen er et alternativ til funktionspolymorfi , nemlig den giver dig mulighed for at oprette funktioner med et mere generelt formål, i stedet for at skabe en række funktioner, der er ens i strukturen, men kun adskiller sig visse steder i de eksekverbare underopgaver. Funktioner, der tager andre funktioner som argumenter eller returnerer funktioner som et resultat, kaldes funktioner af højere orden . Callback-teknikken spiller en vigtig rolle i at opnå kodegenbrug .

Hvorfor bruge tilbagekald

For bedre at forstå årsagerne til at bruge et tilbagekald, overvej den enkle opgave at udføre følgende operationer på en liste over tal: udskriv alle tal, firkanter alle tal, forøg alle tal med 1, sæt alle elementer til nul. Det er klart, at algoritmerne til at udføre disse fire operationer er ens - dette er en løkke, der omgår alle elementerne på listen med en eller anden handling i løkkelegemet, anvendt på hvert element. Dette er en simpel kode, og i princippet kan du skrive den 4 gange. Men lad os overveje et mere kompliceret tilfælde, hvor listen ikke er gemt i hukommelsen, men på disken, og flere processer kan arbejde med listen på samme tid, og det er nødvendigt at løse problemerne med at synkronisere adgang til elementer (flere processer kan udføre forskellige opgaver - fjerne nogle elementer fra listen, tilføje nye, ændre eksisterende elementer på listen). I dette tilfælde vil opgaven med at krydse alle elementerne på listen være ret kompleks kode, som man ikke vil kopiere flere gange. Det ville være mere korrekt at oprette en generel funktion til at krydse elementerne i listen og give programmører mulighed for at abstrahere fra, hvordan gennemløbsalgoritmen fungerer, og kun skrive en tilbagekaldsfunktion til behandling af et enkelt element i listen.

Softwarestrukturering

Strukturering af software gennem tilbagekaldsfunktioner er en meget bekvem og udbredt tilgang, da adfærden af ​​et program med uændret (inklusive lukket) kode kan ændres i et meget bredt område. Dette implementeres på to måder - enten ved "alternativ implementering" af en funktion, eller ved at "føje endnu en funktion til opkaldskæden".

Som regel implementerer udvikleren ikke al programmets funktionalitet gennem tilbagekald, men kun det, der formodes at blive udvidet eller ændret af plugins . For at forbinde plugins leveres en speciel procedure, som erstatter de "standard" inverse funktioner fra udvikleren med alternative fra plugin'et.

Det mest berømte eksempel på denne tilgang er Microsoft Windows -operativsystemet , hvor tilbagekaldsfunktioner kaldes "handler" ("handler"), og det er muligt at indsætte en yderligere procedure mellem to standardprocedurer. Denne tilgang kaldes "hændelsesaflytning" og bruges f.eks.: af antivirus til at kontrollere filer, der tilgås; vira til læsning af tegn indtastet fra tastaturet; netværksfiltre til at indsamle statistik og blokere pakker.

I moderne Unix- og Linux -systemer er det muligt dynamisk at ind- og udlæse kernemoduler, som også er baseret på tilbagekaldsfunktioner. Samtidig er der et modul (kerneudvidelse) FUSE , som igen giver mulighed for, at almindelige brugerprogrammer kan betjene (opsnappe) anmodninger til virtuelle filsystemer.

I software sker der nogle gange en nedbrydning af programmer, der er fuldstændig baseret på tilbagekaldsfunktioner, hvilket forringer kodens læsbarhed lidt, men giver maksimale muligheder for plugins. Et eksempel på et sådant produkt er DokuWiki .

Fordele og ulemper

Fordele:

  • Mulighed for dynamisk ændring af funktionalitet (til- og frakobling af plug-ins/moduler mens programmet kører).
  • Muligheden for et ubegrænset antal varianter af den kaldte funktion uden at ændre den grundlæggende (i denne sammenhæng) kode.
  • Evnen til at indsætte en kaldt funktion ikke kun for alternativ adfærd, men også som en anden (mellemliggende) subrutine - normalt for at spore operationer eller ændre parametre for den næste (kaldte) funktion. Der kan være et hvilket som helst antal af sådanne uafhængige "yderligere led" i opkaldskæden.
  • Understøttelse af tilbagekaldsfunktioner i de fleste moderne programmeringssprog til generelle formål.

Fejl:

  • Ydeevnestraffen forbundet med yderligere "inverse funktion"-opkald er direkte proportional med "funktionsopkaldsomkostningerne" ved kørsel og antallet af yderligere opkald, mens programmet kører.
  • Forringelse af læsbarheden af ​​kildekoden - for at forstå programalgoritmen er det nødvendigt at spore hele kæden af ​​opkald.

Se også

Links