Callback (программирование)

Callback (англ. call — вызов, англ. back — обратный) или фу́нкция обра́тного вы́зова в программировании — передача исполняемого кода в качестве одного из параметров другому коду. Обратный вызов позволяет в функции исполнять код, который задаётся в аргументах при её вызове. Этот код может быть определён в других контекстах программного кода и быть недоступным для прямого вызова из этой функции. Некоторые алгоритмические задачи в качестве своих входных данных имеют не только числа или объекты, но и действия (алгоритмы), которые естественным образом задаются как обратные вызовы.

Применение

Концепция обратного вызова имеет много приложений. Например, некоторые алгоритмы (функции) в качестве подзадачи имеют задачу вычисления хеш-значения от строки. В аргументах при запуске алгоритма (функции) удобно задавать, какую именно функцию использовать для вычисления хеш-значений.

Другой пример алгоритма, которому естественно передавать в аргументе функцию, — алгоритм обхода какого-либо хранилища объектов с применением некоторого действия к каждому объекту. Обратный вызов может выступать в роли этого действия (алгоритма).

Техника программирования обратного вызова в языках программирования, подобных языку C, проста. При вызове основной функции ей просто передаётся указатель на функцию обратного вызова. Классическим примером является функция qsort из библиотеки stdlib. Эта функция позволяет отсортировать массив элементов одинаковой длины. В качестве аргументов она получает адрес первого элемента массива, количество элементов в массиве, размер элемента, и указатель на функцию сравнения двух элементов массива. Эта функция сравнения и есть функция обратного вызова в данном примере:

#include <stdlib.h>
// функция сравнения целых чисел по модулю
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 size = 10;
   int m[size] = {1, -3, 5, -100, 7, 33, 44, 67, -4, 0};
   // сортировка массива m по возрастанию модулей
   qsort(m, size, sizeof(int), compare_abs);
   return 0;
}

Об обратном вызове можно думать как о действии, передаваемом некоторой основной процедуре в качестве аргумента. И это действие может рассматриваться как:

  • подзадача и использоваться для обработки данных внутри этой процедуры;
  • «телефонная связь», используемая для того, чтобы «связываться» с тем, кто вызвал процедуру, при наступлении какого-то события (англ. callback дословно переводится как «звонок обратно»).

Показанный выше пример как раз соответствует первому случаю. Случай, когда обратный вызов используется как «телефонная связь», отражает код, где задаётся функция обработки определённого сигнала:

#include <stdio.h>
#include <signal.h>

volatile sig_atomic_t br = 1;

void sig(int signum)
{
        br=0;
}

int main(int argc, char *argv[])
{
        signal(SIGINT, sig);

        printf("Press break keyboard key combination to stop the program\n");

        while(br);
        
        printf("Received SIGINT, exit\n");

        return 0;
}

В некоторых языках программирования, таких как Common Lisp, Erlang, Scheme, Clojure, PHP, JavaScript, Perl, Python, Ruby и других, есть возможность конструировать анонимные (не именованные) функции и функции-замыкания прямо в выражении вызова основной функции, и эта возможность широко используется.

В технологии AJAX при выполнении асинхронного запроса к серверу необходимо указывать функцию обратного вызова, которая будет вызвана, как только придёт ответ на запрос. Часто эту функцию определяют «прямо на месте», не давая ей никакого определённого имени:

 new Ajax.Request('http://example.com/do_it',
 {
   method: 'post',
   onSuccess: function(transport) { // функция, вызываемая
      window.alert("Done!");        // при успешном выполнении запроса
   },                               // 

   onFailure: function() {          // функция, вызываемая
      window.alert("Error!");       // при ошибке выполнения запроса
   }
 });

Функция обратного вызова используется также в шаблоне проектирования «Наблюдатель» (Observer). Так, например, используя библиотеку Prototype, можно создать «наблюдателя», который следит за нажатиями на элемент с идентификатором "my_button" и при получении события пишет сообщение внутрь элемента "message_box":

 Event.observe ($("my_button"), 'click', function() {
   $("message_box").innerHTML = "Вы нажали на кнопку!"
 });

Функция обратного вызова является альтернативой полиморфизму функций, а именно, позволяет создавать функции более общего назначения вместо того, чтобы создавать серию функций, одинаковых по структуре, но отличающихся лишь в отдельных местах исполняемыми подзадачами. Функции, принимающие в качестве аргументов другие функции или возвращающие функции в качестве результата, называют функциями высшего порядка. Техника обратного вызова играет важную роль для достижения повторного использования кода.

Зачем использовать функции обратного вызова

Для лучшего понимания причин использования обратного вызова рассмотрим простую задачу выполнения следующих операций над списком чисел: напечатать все числа, возвести все числа в квадрат, увеличить все числа на 1, обнулить все элементы. Ясно, что алгоритмы выполнения этих четырёх операций схожи — это цикл обхода всех элементов списка с некоторым действием в теле цикла, применяемый к каждому элементу. Это несложный код, и в принципе можно написать его 4 раза. Но давайте рассмотрим более сложный случай, когда список у нас хранится не в памяти, а на диске, и со списком могут работать несколько процессов одновременно и необходимо решать проблемы синхронизации доступа к элементам (несколько процессов могут выполнять разные задачи — удаления некоторых элементов из списка, добавления новых, изменение существующих элементов в списке). В этом случае задача обхода всех элементов списка будет довольно сложным кодом, который не хотелось бы копировать несколько раз. Правильнее создать функцию общего назначения для обхода элементов списка и дать возможность программистам абстрагироваться от того, как именно устроен алгоритм обхода и писать лишь функцию обратного вызова для обработки отдельного элемента списка.

Структурирование ПО

Структурирование программного обеспечения через функции обратного вызова — очень удобный и широко используемый подход, так как при этом поведение программы с неизменным (в том числе закрытым) кодом можно изменять в очень широких пределах. Это реализуется двумя путями — или «альтернативной реализацией» какой-либо функции, или «добавлением в цепочку вызовов» ещё одной функции.

Как правило, разработчик реализует через обратные вызовы не всю функциональность программы, а лишь ту, которую предполагается расширять или изменять плагинами. Для подключения плагинов предоставляется специальная процедура, которая и заменяет «стандартные» обратные функции от разработчика на альтернативные из плагина.

Самым известным примером такого подхода является операционная система Microsoft Windows, где функции обратного вызова именуются «handler» («обработчик»), и существует возможность вставить дополнительную процедуру между любыми двумя стандартными. Этот подход называется «перехват событий» и используется, например: антивирусами для проверки файлов, к которым производится обращение; вирусами для считывания вводимых с клавиатуры символов; сетевыми фильтрами для сбора статистики и блокирования пакетов.

В современных Unix и Linux системах существует возможность динамической загрузки и выгрузки модулей ядра, работа которых также основана на функциях обратного вызова. При этом существует модуль (расширение ядра) FUSE, который, в свою очередь, предоставляет возможность обычным пользовательским программам обслуживать (перехватывать) запросы к виртуальным файловым системам.

В программном обеспечении иногда встречается декомпозиция программ, полностью основанная на функциях обратного вызова, что несколько ухудшает читаемость кода, но даёт максимальные возможности для плагинов. Пример такого продукта — DokuWiki.

Достоинства и недостатки

Достоинства:

  • Возможность динамического изменения функциональности (подключения и отключения плагинов/модулей при работе программы).
  • Возможность неограниченного количества вариантов вызываемой функции без изменения базового (в данном контексте) кода.
  • Возможность вставки вызываемой функции не только для альтернативного поведения, но и в качестве ещё одной (промежуточной) подпрограммы — обычно для отслеживания операций или изменения параметров для следующей (вызываемой) функции. Таких независимых «дополнительных звеньев» в цепочке вызовов может быть сколько угодно.
  • Поддержка функций обратного вызова в большинстве современных языков программирования общего назначения.

Недостатки:

  • Уменьшение производительности, связанной с дополнительными вызовами «обратной функции», прямо пропорционально «стоимости вызова функции» в среде выполнения и количеству дополнительных вызовов при работе программы.
  • Ухудшение читаемости исходного кода — для понимания алгоритма программы необходимо отслеживать всю цепочку вызовов.

См. также

Ссылки

Read other articles:

Prime Minister of Sudan (2022–present) You can help expand this article with text translated from the corresponding article in Spanish. (April 2022) Click [show] for important translation instructions. View a machine-translated version of the Spanish article. Machine translation, like DeepL or Google Translate, is a useful starting point for translations, but translators must revise errors as necessary and confirm that the translation is accurate, rather than simply copy-pasting machin...

 

LaleilmaninoDari kiri ke kanan: Nino, Ilman dan LaleInformasi latar belakangAsalJakarta, IndonesiaGenrePopPekerjaanMusisipenulis laguproduser rekamanInstrumenVokalgitarkiborTahun aktif2014–sekarangLabelIndependen[a]Artis terkait HIVI! Marion Jola Vidi Aldiano Anggota Arya Aditya Ramadhya Ilman ibrahim Anindyo Baskoro Laleilmanino adalah supergrup pencipta lagu dan produser rekaman asal Jakarta yang terbentuk sejak 2014. Laleilmanino beranggotakan Arya Aditya Ramadhya, Ilman Ibrahim ...

 

Karte des byzantinischen Konstantinopels. Das Forum Bovis liegt rund 350 Meter nördlich des Eleutherion-Hafens an der Mese. Das Forum Bovis (lateinischer Name; mittelgriechisch ὁ Βοῦς ho Bous „der Stier“) war ein öffentlicher Platz im byzantinischen Konstantinopel (heute Istanbul). Das Forum wurde auch als Ort für öffentliche Hinrichtungen und Folterungen genutzt und verschwand nach dem Ende des Byzantinischen Reiches vollständig. Inhaltsverzeichnis 1 Lage 2 Geschichte 3 Archi...

Spencer Ciudad SpencerUbicación en el condado de McCook en Dakota del Sur Ubicación de Dakota del Sur en EE. UU.Coordenadas 43°43′40″N 97°35′31″O / 43.727777777778, -97.591944444444Entidad Ciudad • País Estados Unidos • Estado  Dakota del Sur • Condado McCookFundación 1917Superficie   • Total 0.69 km² • Tierra 0.69 km² • Agua (0%) 0 km²Altitud   • Media 423 m s. n. m.Población (2010) &#...

 

Lelydorp Kofi DjompoKotaKoordinat: 5°41′48″N 55°13′0″W / 5.69667°N 55.21667°W / 5.69667; -55.21667Koordinat: 5°41′48″N 55°13′0″W / 5.69667°N 55.21667°W / 5.69667; -55.21667Negara SurinameDistrikDistrik WanicaLuas • Total149 km2 (58 sq mi)Ketinggian9 m (30 ft)Populasi (2012) • Total18.663 • Kepadatan130/km2 (320/sq mi)Zona waktuUTC-3 (AST) Lelydorp...

 

Gallien zur Zeit Caesars (58 v. Chr.) Vienne zur Zeit der Allobroger Die Allobroger oder Allobrogen[1] (lat. Allobroges) waren ein keltischer Stamm, der Hannibal bei seiner Alpenüberquerung bekämpfte und der schließlich von Rom unterworfen wurde. Inhaltsverzeichnis 1 Etymologie des Namens 2 Geschichte 3 Quellen 4 Literatur 5 Weblinks 6 Einzelnachweise Etymologie des Namens Der Name der Allobrogen bedeutet vermutlich „die in fremden Gebieten wohnen“ (vgl. kymrisch allfro „Frem...

Mattel Inc.JenisPublik (NYSE: MAT)IndustriMainan dan permainanDidirikan1945KantorpusatEl Segundo, CaliforniaTokohkunciRobert A. Eckert, Chairman dan CEO. Kevin M. Farr, CFO.Pendapatan US$ 6,484.892 juta (2013)[1] US$ 6,420.881 juta (2012)[1]Laba operasi US$ 1,168.103 juta (2013)[1] US$ 1,021.015 juta (2012)[1]Laba bersih US$ 903.944 juta (2013)[1] US$ 776.464 juta (2012)[1]Total aset US$ 6,439.626 juta (2013)&#...

 

Henry Scarr Ltd.Henry Scarr employed female welders to build prefabricated ships during the Second World War.TypePrivate companyIndustryShipbuildingFateBought outSuccessorRichard DunstonHeadquartersHessle, East Riding of Yorkshire, England Henry Scarr Ltd. was an English shipbuilding company based in the East Riding of Yorkshire at Hessle on the Humber. Henry Scarr took over an existing shipyard in 1897, and continued to build ships there until 1932, when the site was bought by Richard Dunsto...

 

Nguyễn KimTemple of Nguyễn Kim in HuếBornNguyễn Kim1468 (1468)Thanh HóaDied1545 (aged 76–77)Nghệ An Nguyễn Kim Vietnamese alphabetNguyễn KimChữ Hán阮淦 Posthumous name Vietnamese alphabetTĩnh VươngChữ Hán靖王 Map of Vietnam showing the Mạc in control of the north and central part of Vietnam while the Nguyễn-Trịnh alliance controls the south. Nguyen Kim (Vietnamese: Nguyễn Kim / 阮淦; 1468–1545) was a Vietnamese statesman who was the ...

Zvi Yisrael TauBiographieNaissance 1er janvier 1938 (85 ans)VienneNom de naissance Hans ThauNationalité israélienneFormation Merkaz HaravActivité RabbinFratrie Gerda Elata-Alster (d)Eveline Goodman-ThauAutres informationsParti politique NoamMaître Zvi Yehouda Kookmodifier - modifier le code - modifier Wikidata Zvi Yisrael Tau (hébreu : צבי ישראל טאו , né en 1938) est un rabbin sioniste religieux, disciple du rabbin Zvi Yehouda Kook, et cofondateur et président de l...

 

Kyokunankai Hiromitsu旭南海 廣光Personal informationBornHirokazu Ken (1977-12-14) 14 December 1977 (age 45)Amagi, KagoshimaHeight1.80 m (5 ft 11 in)Weight137 kg (302 lb)CareerStableŌshimaRecord512-493-9DebutMarch, 1993Highest rankMaegashira 16 (September, 2010)RetiredMay, 2011Championships1 (Makushita)* Up to date as of Sep. 2012. Kyokunankai Hiromitsu (born 14 December 1977 as Hirokazu Ken) is a former sumo wrestler from Amagi, Kagoshima, Japan. He made hi...

 

American prison in California Wasco State Prison-Reception Center (WSP) Aerial ViewLocationWasco, CaliforniaCoordinates35°35′38″N 119°24′31″W / 35.5939°N 119.4087°W / 35.5939; -119.4087StatusOperationalSecurity classMediumCapacity2,984Population3,698 (123.9% capacity) (as of January 31, 2023[1])Opened1991Managed byCalifornia Department of Corrections and RehabilitationWardenHeather Shirley[2] Wasco State Prison-Reception Center (WSP) is ...

Administrative unit of Gilgit−Baltistan, Pakistan District of Gilgit−Baltistan administered by Pakistan. in Gilgit-BaltistanAstore District ضلع استورDistrict of Gilgit−Baltistan administered by Pakistan.[1]Nanga Parbat seen from the Rama Valley near Astore District in August 2016Interactive map of Astore districtA map showing Pakistani-administered Gilgit-Baltistan (shaded in sage green) in the disputed Kashmir region[1]Coordinates (Eidgah, Astore): 35°20′...

 

Season of television series Season of television series One PieceSeason 17DressrosaCover for the first Japanese DVD compilation of the seventeenth season as released by Avex PicturesCountry of originJapanNo. of episodes118ReleaseOriginal networkFuji TelevisionOriginal releaseJanuary 19, 2014 (2014-01-19) –June 19, 2016 (2016-06-19)Season chronology← PreviousSeason 16Next →Season 18List of episodes The seventeenth season of the One Piece anime television series w...

 

American politician This article includes a list of general references, but it lacks sufficient corresponding inline citations. Please help to improve this article by introducing more precise citations. (December 2020) (Learn how and when to remove this template message) Feramorz Little, c. 1850s Feramorz Little (June 14, 1820 – August 14, 1887) was the mayor of Salt Lake City, Utah Territory, from 1876 to 1882. Little was born in Aurelius, New York, to James Little and Susan Young. His mot...

Polish academician and jurist Małgorzata Manowska15th First President of the Supreme CourtIncumbentAssumed office 26 May 2020Nominated byAndrzej DudaPreceded byMałgorzata Gersdorf Personal detailsBornMałgorzata Soporek (1964-09-22) September 22, 1964 (age 59)Warsaw, PolandEducationUniversity of Warsaw Małgorzata Manowska (born 22 September 1964) is a Polish academician and jurist who serves as the First President of the Supreme Court and as the Chief Justice of the State Tribunal...

 

Saša Kalajdžić Kalajdžić bermain untuk VfB Stuttgart pada 2022Informasi pribadiTanggal lahir 7 Juli 1997 (umur 26)Tempat lahir Wina, AustriaTinggi 200 cm (6 ft 7 in)[1]Posisi bermain PenyerangInformasi klubKlub saat ini Wolverhampton WanderersNomor 18Karier senior*Tahun Tim Tampil (Gol)2014–2016 SR Donaufeld Wina 18 (7)2016–2018 Admira Wacker II 33 (13)2016–2019 Admira Wacker 33 (11)2019–2022 VfB Stuttgart 57 (23)2022– Wolverhampton Wanderers 0 (0)Ti...

 

Species of gastropod Phos senticosus Shell of Phos senticosus Scientific classification Kingdom: Animalia Phylum: Mollusca Class: Gastropoda (unranked): clade Caenogastropodaclade Hypsogastropodaclade Neogastropoda Superfamily: Buccinoidea Family: Buccinidae Subfamily: Buccininae Genus: Phos Species: P. senticosus Binomial name Phos senticosus Synonyms[1] Buccinum senticosum (Linnaeus, 1758) Cancellaria senticosa (Linnaeus, 1758) Murex senticosus Linnaeus, 1758 Phos senticosus, c...

Historic house in New Hampshire, United States United States historic placeDr. Solomon M. Whipple HouseU.S. National Register of Historic Places Show map of New HampshireShow map of the United StatesLocationMain St., New London, New HampshireCoordinates43°24′48″N 71°59′5″W / 43.41333°N 71.98472°W / 43.41333; -71.98472Area0.6 acres (0.24 ha)Built1850 (1850)Architectural styleGreek RevivalNRHP reference No.85002187[1]Added to ...

 

Not to be confused with Ahmed Rashid. Ahmed ErrachidiMohamad Al Ahmed Rachidi's Guantanamo detainee assessmentBorn (1966-03-16) March 16, 1966 (age 57)[1]Tangier, MoroccoArrested2002Bannu, PakistanReleased2007MoroccoCitizenshipMoroccoDetained at GuantanamoISN590Charge(s)no charge (extrajudicial detention)StatusrepatriatedOccupationchef Ahmed Rashidi (also known as Ahmed Errachidi) is a citizen of Morocco who was held in extrajudicial detention in the United States Guantanamo...

 

Strategi Solo vs Squad di Free Fire: Cara Menang Mudah!