closures&callbacks

 

引用文章原文地址:(声明:文章只为自己总结知识,内容东拼西凑,版权归以下作者所有。)

1. Wikipedia: callback(computer science)

2. Implement callback routines in Java By John D. Mitchell, JavaWorld.com, 06/01/96

3. Why is Python more fun than Java? Brian M. Clapper

 

最近在读Eckel的Thinking in Java,读到Inner Class那一章碰到两个概念不是很清楚,一个是callback,另一个是closures,网上搜了搜,整理如下。

先说callback,粘一段wikipedia的概念。

词条: callback 来自:wikipediaIn computer programming, a callback is executable code that is passed as an argument to other code. It allows a lower-level software layer to call a subroutine (or function) defined in a higher-level layer.

 

(下面很多是翻译wikipedia的东西,翻译自然会加入了自己的理解,出错难免。)

为什么需要callback呢?

比如说你想对一个序列中的每个元素进行一次任意的操作,一种方案是遍历这个序列,直接对每个元素进行操作,这是最直接的,缺点是会产生代码冗余,每次遍历都要写重复的代码。另一种方案是写一个泛型的库函数,将序列传递给库函数,在函数的内部遍历操作这个序列,一定程度上消除了代码冗余,问题是使用库函数的应用程序的要求是不可预期的,不可能写出所有满足应用程序要求的库函数。第三种方案当然就是callback,应用程序对序列进行遍历,对每个元素调用callback函数,解决了上述两个问题。

一个用C写的示例:

程序功能:遍历一个整形的数组找出第一个大于5的元素,并给出索引(index)

遍历的方案:

 1    int  i;
 2   
 3    for  (i  =   0 ; i  <  length; i ++ )
 4   {
 5        if  (array[i]  >   5
 6       { 
 7            break ;
 8       }
 9   }
10   
11    if  (i  <  length) 
12   {
13       printf( " Item %d\n " , i);
14   }
15    else
16   {
17       printf( " Not found\n " );
18   }


callback的方案:

 1  /*  LIBRARY CODE  */
 2    int  traverseWith( int  array[], size_t length, 
 3                     int  ( * callback)( int  index,  int  item,  void   * param), 
 4                     void   * param)
 5   {
 6        int  exitCode  =   0 ;
 7        for  ( int  i  =   0 ; i  <  length; i ++ ) {
 8           exitCode  =  callback(i, array[i], param);
 9            if  (exitCode  !=   0 ) { 
10                break ;
11           }
12       }
13        return  exitCode;
14   }
15   
16    /*  APPLICATION CODE  */
17    int  search ( int  index,  int  item,  void   * param)
18   {
19        if  (item  >   5 ) {
20            * ( int   * )param  =  index;
21            return   1 ;
22       }  else  {
23            return   0 ;
24       }
25   }
26   
27    /*  (in another function)  */
28    int  index;
29    int  found;
30   found  =  traverseWith(array, length,  & search,  & index);
31    if  (found) {
32       printf( " Item %d\n " , index);
33   }  else  {
34       printf( " Not found\n " );
35   }
36 
37 

注意 search函数的最后一个参数param,callback函数通常用这样一个指针参数来操作它的scope之外的数据,在这里是用来存放索引的值。只有statically scoped language的语言(如C/C++)才需要这样的参数,Lexically scoped languages的语言(如Lisp)支持closure因而不需要这个参数,closure是一个可以调用的对象,它可以保留创建它的那个scope里的信息,Java中的Inner Class就是一个面向对象的closure,因为它可以通过一个内置的引用访问包含它类的所有成员,包括private成员。

可以看到上面的callback函数是通过一个函数指针实现的,Java不支持函数指针,那么再Java中如何来实现 callback函数呢?

Jave支持Interface,利用它我们可以实现callback的效果。技巧就是把我们要调用的callback函数封装在一个简单的接口里。任何实现这个接口的object都可以用来callback. 下面我写的Java版的callback.

 1  import  java.util.ArrayList;
 2  import  java.util.Collections;
 3  import  java.util.List;
 4  import  java.util.Arrays;
 5 
 6  interface  Matcher < T >
 7  {
 8       // test if t meets certain requirement, index is the index of t in a List
 9       public   boolean  matches( int  index, T t);
10  }
11  class  MyLib
12  {
13       // Find the fisrt item in list that meets the requirement of matcher
14       public   static   < T >   boolean  findFirstMatch(List < T >  list, Matcher < T >  matcher)
15      {
16           boolean  found  =   false ;
17           for ( int  i  =   0 ; i  <  list.size(); i ++ )
18          {
19               if (matcher.matches(i,list.get(i)))
20              {
21                  found  =   true ;
22                   break ;
23              }
24          }
25           return  found;
26      }
27  }
28  class  Value
29  {
30       int  val;
31       public  Value( int  val)
32      {
33           this .val  =  val;
34      }
35  }
36  public   class  CallbackAndColsureExample
37  {
38       public   static   final  List < Integer >  NUMBERS  =  
39          Collections.unmodifiableList(Arrays.asList( 1 , 4 , 6 , 10 , 3 , 9 , 7 ));
40       public   static   void  main(String[] args)
41      {
42           final   int  base  =   5 ;
43           final  Value index  =   new  Value( - 1 );
44          Matcher < Integer >  biggerThanBaseMatcher  =   new  Matcher < Integer > ()
45          {
46               public   boolean  matches( int  idx, Integer val)
47              {
48                   if (val  >  base)
49                  {
50                      index.val  =  idx;
51                       return   true ;
52                  }
53                   else   return   false ;
54              }
55          };
56           boolean  found  =  MyLib.findFirstMatch(CallbackAndColsureExample.NUMBERS, biggerThanBaseMatcher);
57           if (found) System.out.println( " item found at index  "   +  String.valueOf(index.val));
58           else  System.out.println( " item not found " );
59      }
60  }

 

我们用Matcher<T>这个接口封装了一个callback函数,在类CallbackAndColsureExample的内部我们用了一个匿名的Inner Class实现了Matcher<T>接口,并定义了一个对象biggerThanBaseMatcher,通过biggerThanBaseMatcher我们就可以调用callback函数了。注意这个Inner Class形成了一个closure, 所以在它的内部可以访问在Outer calss里定义的index.

转载于:https://www.cnblogs.com/sirkay777/archive/2008/12/12/1353844.html

你可能感兴趣的:(closures&callbacks)