Callback ( anglicky call - call, anglicky back - reverse) nebo funkce callback v programování - předání spustitelného kódu jako jednoho z parametrů jiného kódu. Zpětné volání umožňuje funkci spustit kód, který je zadán v argumentech , když je volána. Tento kód může být definován v jiných kontextech kódu a nelze jej přímo volat z této funkce. Některé algoritmické úlohy mají jako vstup nejen čísla nebo objekty, ale také akce (algoritmy), které jsou přirozeně specifikovány jako zpětná volání.
Koncept zpětného volání má mnoho aplikací. Například některé algoritmy (funkce) mají jako dílčí úkol vypočítat hodnotu hash z řetězce. V argumentech při spouštění algoritmu (funkce) je vhodné určit, kterou funkci použít k výpočtu hodnot hash.
Dalším příkladem algoritmu, pro který je přirozené předat funkci jako argument, je algoritmus pro procházení nějakým úložištěm objektů a aplikování nějaké akce na každý objekt. Jako tato akce (algoritmus) může fungovat zpětné volání.
Technika programování zpětného volání v programovacích jazycích jako C je jednoduchá. Když je volána hlavní funkce , je jí jednoduše předán ukazatel na funkci zpětného volání. Klasickým příkladem je funkce qsortz knihovny stdlib . Tato funkce seřadí pole bajtových bloků stejné délky. Jako argumenty obdrží adresu prvního prvku pole, počet bloků v poli, velikost bloku bajtů a ukazatel na funkci pro porovnání dvou bloků bajtů. Tato porovnávací funkce je v tomto příkladu funkcí zpětného volání:
#include <stdlib.h> // funkce pro porovnání celých čísel modulo int Compare_abs ( const void * a , const void * b ) { int a1 = * ( int * ) a ; int b1 = * ( int * ) b ; návrat abs ( a1 ) - abs ( b1 ); } int main () { int velikost = 10 ; int m [ velikost ] = { 1 , -3 , 5 , -100 , 7 , 33 , 44 , 67 , -4 , 0 }; // řazení pole m ve vzestupných modulech qsort ( m , size , sizeof ( int ), Compare_abs ); návrat 0 ; }Zpětné volání si můžete představit jako akci předávanou jako argument nějaké hlavní proceduře. A tato akce může být viděna jako:
Výše uvedený příklad přesně odpovídá prvnímu případu. Případ, kdy je zpětné volání použito jako „telefonní spojení“, odráží kód, kde je dána funkce pro zpracování konkrétního signálu:
#include <stdio.h> #include <signal.h> těkavý sig_atomic_t br = 1 ; void sig ( int signum ) { br = 0 ; } int main ( int argc , char * argv []) { signál ( SIGINT , sig ); printf ( "Pro zastavení programu stiskněte kombinaci kláves přerušení \n " ); zatímco ( br ); printf ( "Přijat SIGINT, ukončení \n " ); návrat 0 ; }V některých programovacích jazycích, jako je Common Lisp , Erlang , Scheme , Clojure , PHP , JavaScript , Perl , Python , Ruby a dalších, je možné konstruovat anonymní (nepojmenované) funkce a uzavírací funkce přímo ve výrazu volání hlavní funkce a tato příležitost je hojně využívána.
V technologii AJAX musíte při vytváření asynchronního požadavku na server zadat funkci zpětného volání, která bude volána, jakmile dorazí odpověď na požadavek. Tato funkce je často definována „na místě“, aniž by jí byl přidělen jakýkoli konkrétní název:
nový Ajax . Požadavek ( 'http://example.com/do_it' , { method : 'post' , onSuccess : function ( transport ) { // funkce volaná oknem . alert ( "Hotovo!" ); // pokud byl požadavek úspěšný } , // onFailure : function () { // funkce volaná oknem . upozornění ( "Chyba!" ); // při chybě provádění požadavku } });Funkce zpětného volání se také používá v návrhovém vzoru Observer . Takže například pomocí knihovny Prototype můžete vytvořit „pozorovatele“, který sleduje kliknutí na prvek s identifikátorem "my_button", a když je přijata událost, zapíše do prvku zprávu "message_box":
událost . pozorovat ( $ ( "my_button" ), 'click' , function () { $ ( "message_box" ). innerHTML = "Klikli jste na tlačítko!" });Funkce zpětného volání je alternativou k polymorfismu funkcí , konkrétně umožňuje vytvářet funkce obecnějšího účelu namísto vytváření řady funkcí, které mají stejnou strukturu, ale liší se pouze na určitých místech ve spustitelných dílčích úloze. Funkce, které ve výsledku berou jiné funkce jako argumenty nebo vracejí funkce, se nazývají funkce vyššího řádu . Technika zpětného volání hraje důležitou roli při dosahování opětovného použití kódu .
Chcete-li lépe porozumět důvodům použití zpětného volání, zvažte jednoduchý úkol provedení následujících operací se seznamem čísel: vytisknout všechna čísla, odmocnit všechna čísla, zvýšit všechna čísla o 1, nastavit všechny prvky na nulu. Je jasné, že algoritmy pro provádění těchto čtyř operací jsou podobné - jedná se o smyčku, která obchází všechny prvky seznamu s nějakou akcí v těle smyčky aplikovanou na každý prvek. Jedná se o jednoduchý kód a v zásadě jej můžete napsat 4krát. Uvažujme ale složitější případ, kdy seznam není uložen v paměti, ale na disku a se seznamem může pracovat více procesů současně a je nutné vyřešit problémy se synchronizací přístupu k prvkům (několik procesů může provádět různé úkoly - odstranění některých prvků ze seznamu, přidání nových, změna existujících položek v seznamu). V tomto případě bude úkolem procházet všechny prvky seznamu poměrně složitým kódem, který by člověk nechtěl vícekrát kopírovat. Správnější by bylo vytvořit univerzální funkci pro procházení prvků seznamu a umožnit programátorům abstrahovat od toho, jak algoritmus procházení funguje, a napsat pouze funkci zpětného volání pro zpracování jednoho prvku seznamu.
Strukturování softwaru pomocí funkcí zpětného volání je velmi pohodlný a široce používaný přístup, protože chování programu s nezměněným (včetně uzavřeného) kódu lze měnit ve velmi širokém rozsahu. To se realizuje dvěma způsoby – buď „alternativní implementací“ funkce, nebo „přidáním další funkce do řetězce volání“.
Vývojář zpravidla neimplementuje všechny funkce programu prostřednictvím zpětných volání, ale pouze tu, která má být rozšířena nebo upravena pomocí pluginů . Pro připojení pluginů je k dispozici speciální postup, který nahradí „standardní“ inverzní funkce od vývojáře alternativními z pluginu.
Nejznámějším příkladem tohoto přístupu je operační systém Microsoft Windows , kde se funkce zpětného volání nazývají "handler" ("handler") a mezi libovolné dvě standardní procedury je možné vložit další proceduru. Tento přístup se nazývá „zachycování událostí“ a používají jej například: antiviry ke kontrole souborů, ke kterým se přistupuje; viry pro čtení znaků zadávaných z klávesnice; síťové filtry pro sběr statistik a blokování paketů.
V moderních unixových a linuxových systémech je možné dynamicky načítat a uvolňovat moduly jádra, které jsou rovněž založeny na funkcích zpětného volání. Zároveň existuje modul (rozšíření jádra) FUSE , který zase poskytuje běžným uživatelským programům možnost obsluhovat (zachycovat) požadavky na virtuální souborové systémy.
V softwaru někdy dochází k rozkladu programů, který je zcela založen na funkcích zpětného volání, což mírně zhoršuje čitelnost kódu, ale dává maximální možnosti pro pluginy. Příkladem takového produktu je DokuWiki .
výhody:
nedostatky: