回調函數,就是回頭再調用的函數

又遇到了回調函數,此次打算寫下來分享一下。javascript

所謂回調函數,或者在面嚮對象語言裏叫回調方法,簡單點講,就是回頭在某個時間(事件發生)被調用的函數。java

再詳細點:就是一個函數A,做爲參數,傳入了另外一個函數B,而後被B在某個時間調用。python

這裏能夠有疑問了,既然是一個函數調用另外一個函數,能夠在函數體裏面調用啊,爲何還要把函數做爲參數傳到另外一個函數裏被調用?況且還有一些語言(好比java)不支持把函數做爲參數。android

對的,確實能夠在函數體裏調用另外一個函數,功能上好像是沒差異的,可是這裏有一個問題,就是你要調用的這個函數被寫死了,也就是說這樣函數B只能調用函數A了,這樣若是在另外一個情景下,有個與A不一樣實現的函數C也須要在B的某個時刻被調用,那怎麼辦。c++

下面繼續說回調函數,在c/c++裏,回調函數可使用函數指針做爲參數被另外一個函數調用;在c#裏,可使用委託,若是是事件方法的話,還有event關鍵字;在python和javascript裏,能夠直接把函數當對象傳參,這些語言都很好實現回調函數(方法),但是, java呢? 先說點題外話,自從學了C#,就不喜歡java了,曾經一度打算之後再也不用java,但是現實並無那麼理想,我如今要作android,因此仍是不能放下java,並且今天遇到這個回調函數的問題,也是從java裏遇到的,我我的以爲,在這個博客裏出現的語言,除了java外,對於回調,均可以既容易,又好理解的實現,可是java,我以爲並非那樣,否則我也不會來寫這篇博客。c#

好了繼續說,關於java中的回調方法的實現。這篇博客的重點就是說java的。 在java中,回調方法是用借用接口來實現的,我在網上找到一句話:app

「把實現某一接口的類所建立的對象的引用,賦值給該接口聲明的接口變量,那麼該接口變量就能夠調用被實現的接口的方法」。ide

很繞哈,簡單解釋下:
有一個接口,接口裏有一個方法(這個方法就是要回調的方法):函數

interface CallBackInterface {
    void callBackMethod();
}

咱們知道,接口對象不能直接用,由於裏面的方法都沒有實現。因此要找個類實現這個接口。
因此如今加一個類,實現這個接口:this

interface CallBackInterface {
    void callBackMethod();
}

class CallBackClass implements CallBackInterface{

    @Override
    public void callBackMethod() {
        System.out.println("hello");
    }
}

好了,最後一步:把實現了接口的類的對象賦值給聲明的接口變量(我給寫進一個方法裏了,而後外面加了個類的殼子):

public class CallBackTest {

    interface CallBackInterface {
        void callBackMethod();
    }

    class CallBackClass implements CallBackInterface {

        @Override
        public void callBackMethod() {
            System.out.println("hello");
        }
    }

    public void showCallBack() {
        CallBackInterface itfs = new CallBackClass();
        itfs.callBackMethod();
    }
}

如今能夠調用試試看了:

public class Test {
    public static void main(String[] args) {
        new CallBackTest().showCallBack();
    }
}

沒意外的話,會成功輸出hello,反正我這邊是的.

例子看完了,因此說我作了什麼呢? 再詳細點說,咱們有一個要在某一個方法裏被調用的方法(這個方法就是回調方法), 前面咱們也說了,最好不要直接把想要回調方法作的事直接寫在調用方法裏, 又由於java裏無法把方法當作參數傳遞,因此咱們只好把這個回調方法放在了接口裏(爲何不是類?不是抽象類?而是接口?你能夠本身去找下抽象類與接口的異同,本身解決這個問題)。有接口的話,就要被類實現,而後,只要是給接口的對象賦予實現類的對象,這個接口的對象就能夠調用那個方法了。理解這裏的話,有一個重點,就是多態, 這裏用到的多態知識就是,接口的對象能夠順利被子類賦值,而且調用子類的重寫方法(類也有相似的概念)。

再多說一點,這裏任何實現了CallbackInterface接口的類,均可以像下面這樣放在new後面(就是賦值):

public class CallBackTest {
    interface CallBackInterface {
        void callBackMethod();
    }

    class CallBackClass implements CallBackInterface {

        @Override
        public void callBackMethod() {
            System.out.println("hello");
        }
    }

    class Controller {
        private CallBackInterface cbitf;
        // 這個boolean只是爲了模擬有事件,沒啥實用價值
        public boolean somethingHappend;
        // 這裏確實能夠直接把CallBackClass作參數,並且省掉接口的定義
        // 可是這樣作的話,就像是回調函數直接寫在了調用函數裏同樣
        // 不明白的話就好好理解下"約定"和"調用者無論回調函數是怎麼實現的"吧
        public Controller(CallBackInterface itfs) {
            somethingHappend = true;
            this.cbitf = itfs;
        }

        public void doSomething() {
            if(somethingHappend) {
                cbitf.callBackMethod();
            }
        }
    }

    public void showCallBack() {
        CallBackClass cbc = new CallBackClass();
        Controller ctrlr = new Controller(cbc);
        ctrlr.doSomething();
        // 其實上面也能夠這樣寫在一行裏
        // new Controller(new CallBackClass()).doSomething();
    }
}

最後多說一點,其實這種應用在android裏會常常遇到,我就是在學android的時候遇到的。

相關文章
相關標籤/搜索