回調函數

回調函數或簡稱回調(callback),是計算機編程中對某一段可執行代碼引用,它被作為參數傳遞給另一段代碼;預期這段代碼將回調(執行)這個回調函數作為自己工作的一部份。這種執行可以是即時的,如在同步回調之中;也可以在後來的時間點上發生,如在異步回調之中。

回調通常與原始調用者處於相同的抽象層

編程語言以不同方式支持回調,經常將它們實現為子例程lambda表達式函數指針

使用

回調的用途十分廣泛。例如,假設有一個函數,其功能為讀取配置文件並由文件內容設置對應的選項。若這些選項由散列值所標記,則讓這個函數接受一個回調會使得程序設計更加靈活:函數的調用者可以使用所希望的散列算法,該算法由一個將選項名轉變為散列值的回調函數實現;因此,回調允許函數調用者在運行時調整原始函數的行為。

回調的另一種用途在於處理信號或者類似物。例如一個POSIX程序可能在收到SIGTERM信號時不願立即終止;為了保證一切運行良好,該程序可以將清理函數註冊為SIGTERM信號對應的回調。

回調亦可以用於控制一個函數是否作為:Xlib允許自定義的謂詞用於決定程序是否希望處理特定的事件。

例子

下列C語言代碼描述了利用回調處理POSIX風格的信號(在本示例中為SIGUSR1)的過程。值得注意的是,在處理信號的過程中,調用printf(3)不安全的

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

void sig(int signum)
{
    printf("Received signal number %d!\n", signum);
}

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

    pause();
   
    return 0;
}

系統調用pause(3)會導致這個例子不做任何有意義的事,但這樣做可以給你充分的時間來給這個進程發送信號。(在類Unix系統上,可以調用kill -USR1 <pid>,其中<pid>代表該程序的進程號。運行之後,該程序應當會有反應。)

實現

回調的形式因程序設計語言而有差別。

  • Objective-C中允許利用@selector關鍵字傳遞SEL類型的函數名。在實現中,SEL類型被定義為函數名字符串。
  • .NET語言中用到的事件與事件處理函數提供了用於回調的通用語法。
  • Apple或是LLVM的C語言擴展中,包含稱為的語言特性,可以作為函數的參數傳遞,作為回調的一種實現。
  • 在缺少函數類型的參數的面向對象的程序語言中,例如Java,回調可以用傳遞抽象類或接口來模擬。回調的接收者會調用抽象類或接口的方法,這些方法由調用者提供實現。這樣的對象通常是一些回調函數的集合,同時可能包含它所需要的數據。這種方法在實現某些設計模式時比較有用,例如訪問者模式觀察者模式策略模式
  • C++允許對象提供其自己的函數調用操作的實現,即重載operator()。標準模板庫和函數指針一樣接受這類對象(稱為函數對象)作為各種算法的參數。

參見

參考資料

  1. ^ Perl Cookbook - 11.4. Taking References to Functions. [2008-03-03]. (原始內容存檔於2008-04-10). 
  2. ^ Advanced Perl Programming - 4.2 Using Subroutine References. [2008-03-03]. (原始內容存檔於2008-07-05). 

外部連結