目的:
在形如
- func(){
- head head head...
- act();
- tail tail tail...
- }
的代碼中,常常會出現 act 并不是特定的某個動作,可能需要外界定制,如
- void main(){
- int a = 2, b = 3;
- double r=a + b;
- printf("%lf/n", r);
- }
第 4 行的運算式可能是 a-b, a * b, 或者 sqrt(a*a + b*b),此時便需要將運算式傳進 main 函數。
假如運算式有幾種可以確定,可以使用:
- void main(char op){
- int a = 2, b = 3;
- double r= 0;
- switch(op){
- case '+': r = a + b; break;
- case '-' : r = a - b ; break;
- case '*' : r = a * b ; break;
- case '?' : r = sqrt(a * a + b * b); break;
- }
- printf("%lf/n", r);
- }
代碼看起來比較臃腫。不幸的是,事先并不知道确定有哪些表達式,所以雖然這么賣力,也沒能解決問題。
我們期望的方案應該是這樣的:
- void main(expr){
- int a = 2, b = 3;
- double r = expr(a, b);
- printf("%lf/n", r);
- }
這個。。好像泄露謎底了。 這種由另外的開發階段來提供表達式的方式叫回調。
在 c 語言里,能做到這樣的方法是函數指針:
- void fun(double(*expr)(int, int)){
- int a = 2, b = 3;
- double r = expr(a, b);
- printf("%lf/n", r);
- }
- double add(int a, int b){return a + b;}
- double subtract(int a, int b){return a - b;}
- double multi(int a, int b){return a * b;}
- double xian(int a, int b){return sqrt(a * a + b * b);}
- void main(){
- fun(&add);
- func(&subtract);
- func(&multi);
- func(&xian);
- }
此方法順利的實現了回調的目的。所以在以後還可以方便的塞新算法進去。
在 java 里沒有函數指針,所以我們不能指望函數指針這種方式,萬一指錯了怎么辦,函數指針好用,也很危險。在 java 里的做法有這么幾種。
第一、聲明一個表達式類或接口,每一種運算都這個類派生,如下:
- public class Test {
- interface Expr {
- double eval(int a, int b);
- }
- private static void fun(Expr expr) {
- int a = 2, b = 3;
- double r = expr.eval(a, b);
- System.out.println(r);
- }
- public static void main(String[] args) {
- fun(new Expr() {
- @Override
- public double eval(int arg0, int arg1) {
- return arg0 + arg1;
- }
- });
- fun(new Expr() {
- @Override
- public double eval(int arg0, int arg1) {
- return arg0 - arg1;
- }
- });
- fun(new Expr() {
- @Override
- public double eval(int arg0, int arg1) {
- return arg0 * arg1;
- }
- });
- fun(new Expr() {
- @Override
- public double eval(int arg0, int arg1) {
- return Math.sqrt(arg0 * arg0 + arg1 * arg1);
- }
- });
- }
- }
這段代碼看上去比較長。幸運的是在 eclipse 的幫助下,也沒打幾個字。
第二種方法、使用 override 特性:
- public abstract class Test {
- public void fun() {
- int a = 2, b = 3;
- double r = expr(a, b);
- System.out.println(r);
- }
- abstract double expr(int a, int b);
- public static void main(String[] args) {
- new Test() {
- @Override
- double expr(int arg0, int arg1) {
- return arg0 + arg1;
- }
- }.fun();
- new Test() {
- @Override
- double expr(int arg0, int arg1) {
- return arg0 - arg1;
- }
- }.fun();
- new Test() {
- @Override
- double expr(int arg0, int arg1) {
- return arg0 * arg1;
- }
- }.fun();
- new Test() {
- @Override
- double expr(int arg0, int arg1) {
- return Math.sqrt(arg0 * arg0 + arg1 * arg1);
- }
- }.fun();
- }
- }
最後是來自函數式編程家族的 javascript:
- function fun(expr){
- var a=2, b = 3;
- var r = expr(a, b);
- alert(r);
- }
- fun(function(){return a + b;});
- fun(function(){return a - b;});
- fun(function(){return a * b;});
- fun(function(){return Math.sqrt(a * a + b * b);});
代碼很短很瀟灑。