1. 程式人生 > >回撥函式是什麼鬼(java)

回撥函式是什麼鬼(java)

回撥函式(callback)是什麼鬼?(java)

這篇文章我們來談一談回撥函式,什麼是回撥函式?

下面是百度百科的解釋:

回撥函式就是一個通過函式指標呼叫的函式。如果你把函式的指標(地址)作為引數傳遞給另一個函式,當這個指標被用來呼叫其所指向的函式時,我們就說這是回撥函式。回撥函式不是由該函式的實現方直接呼叫,而是在特定的事件或條件發生時由另外的一方呼叫的,用於對該事件或條件進行響應。

所以說回撥函式其實就是對某一事件的相應,也就是在某動作發生前或發生後執行呼叫的函式就稱為回撥函式。

實現簡單的回撥

現在我們來實現簡單的回撥函式,既然回撥函式是某事件發生後呼叫的方法,那麼我們只需要在相應的邏輯處理之後呼叫回撥函式就好啦,例如下面:

void doSomething(){
    /*
    *
    * do someting here
    *
    */
    callback();
}

看就是這麼簡單在完成了相應的動作do someting 後callback()肯定會執行,這就相當於完成事件do someting後觸發了事件。

好了,但是上面的簡單回撥例子有個問題,就是callback()函式是被硬編碼到了doSomething()當中,這段程式毫無可重用性,毫無拓展性。

改進版的回撥

上面的簡單回撥雖說實現了事件觸發回撥函式的功能,但是因為是把callback()硬編碼到了doSomething()中所以缺毫無實用性,程式碼毫無可重用性。

如果說我現在想修改callback()我就要大費周章的在doSomething()裡面去改動,所以能否有一種方法能夠把我自己想要回調的函式傳遞進去或許好一點呢。

大家可能馬上想到了C++的函式指標了,沒錯我們只要在doSomething()的引數列表裡面加上一個callback()的函式指標形參就能夠完美的實現我們想要的功能,在dosomething之後呼叫任何我們想要的函式(邏輯),只要我們能夠傳遞函式的指標到doSomething()中就可以了。

但是有一個問題在java裡面沒有指標這種神器,但是我們可以通過類(class)傳遞到方法從而傳遞我們自己實現的任意回撥函式到doSomething()裡面,類似程式碼如下:

class SomeClass{
    public void callback(){
        /*
        *  this is callback
        */
    }
}

下面就是把SomeClass傳遞到doSomething()裡面,再由doSomething()呼叫SomeClass裡面的callback()。

void doSomething(SomeClass someclass){
    /*
    *
    *  do something here
    *
    */
    someclass.callback();
}

好了,多麼漂亮啊,只要傳遞類就能夠實現類似C++的函式指標的功能,現在我們只要把不同的類傳遞到doSomething(SomeClass someclass)裡面就可以實現事件發生後呼叫任何自己想要的回撥函式。

好了,但是還是有一個問題就是doSomething(SomeClass someclass)這個函式只認識SomeClass這個類,加入其他類傳入進來,想都不用想可能會發生異常。

下面就來解決這個問題。

終極版的回撥

上面我們知道加入我們傳遞別的類例項到doSomething(SomeClass someclass)裡面將會發生異常,因為doSomething(SomeClass someclass)只認得SomeClass型別的類,那怎麼解決呢?

你可能會想讓其他的類繼承SomeClass並且重寫callback()函式,就可以把其他的類傳遞到doSomething(SomeClass someclass)裡了,其他的事情交給多型來管吧,就像下面的程式碼:

class otherClass extends SomeClass{

        @Override
        public void callback(){
        /*
        *  this is callback
        */
    }
}

好了,既然能想到繼承SomeClass來實現,那麼為什麼不乾脆就把SomeClass定義成介面。

嗯,接下來我們就吧SomeClass定義成介面。

interface CallbackInterface{
    void callback();
}

好了,這樣在doSomething(SomeClass someclass)函式裡面就可以吧形參改成介面SomeInterface了

void doSomething(CallbackInterface someinterface){
    /*
    *
    *  do something here
    *
    */
    someinterface.callback();
}

嗯,接下來只要任意的類實現CallbackInterface介面就可以實現自己的callback(),並且傳遞進doSomething(CallbackInterface someinterface)函式,型別的問題就交給多型吧,感謝多型,感謝世界。

下面就是實現了CallbackInterface介面的類SomeClassImp:

class SomeClassImp implements CallbackInterface{

    void callback(){
        /*
        *  this is callback
        */
    }
}

下面我們只需要把SomeClassImp傳遞到doSomething(CallbackInterface someinterface)函式:

doSomething(new SomeClassImp());

好了,現在doSomething()不跟任何類有瓜葛了,現在的doSomething()只認CallbackInterface介面,只要看到傳遞進來的類實現了CallbackInterface介面通通都可以通過,其他的一律報異常,哈哈。

這樣我們只需要在需要實現自己的callback的時候實現CallbackInterface介面就OK了。

總結

感謝多型,感謝介面,感謝世界

喜歡我的內容嗎?
關注下面的公眾號吧
這裡寫圖片描述