Java中接口对象实现回调
看mahout的源代码时发现
private final Retriever<Long,Recommendations> recommendationsRetriever;
其中Retriever是个接口,对这个接口对象表示不解,为什么要这样做呢?
在C中如果要调用某个函数,可以先声明一个函数指针,然后就可以调用这个函数,简单描述如下
首先需要定义一个函数指针:typedef void (*callback)(int,int,...)
接下来就可以使用fun来绑定某个对应的函数,如
void fun(int a,int b,..){
...
}
绑定fun: callback = &fun;
最后就可以调用fun函数了,如callback(1,2);
可是为什么要这样麻烦操作呢,不是可以直接使用fun(1,2)就可以了吗?
我的理解是回调函数有两个作用:1.当你不能直接调用该函数,只能期望先把函数当参数传递进来日后使用的时候,总之一句话你没办法直接调用那个函数,什么时候会出现这种没法直接调用该函数的情况呢?一个简单的例子就是你不知道谁将会调用该函数。2.代码复用。好吧,有点模糊,举个很简单的例子(下面这个graph_foreach代码具体可见http://www.cnblogs.com/abc123456789/p/3456692.html)
void graph_foreach(Graph g, char svex, void (*f)(Graph g, char svex, char tvex, void *data)){ ... }
这个函数使用了一个回调函数,它可能希望对某些边(里面会有条件判断)进行某些函数处理(可能有处理1,处理2)
于是它会这么使用 graph_foreach(g,g->alist[idx]->vexname,print_edge2dot);其中print_edge2dot就是一个函数指针
当然它也可以这样使用 graph_foreach(g,g->alist[idx]->vexname,print_edge2plain);其中print_edge2plain是另一个函数指针,于是代码复用。
而如果print_edge2dot函数在graph_foreach中是不可见无法调用的呢,则只能传递参数进去了。这个说到底就和为什么我们需要参数是一个问题了?我觉得是改变变量的作用域
Java中接口是一些纯虚函数的集合,Java要求接口中不能有普通成员变量,也不能具有非纯虚函数,对应C++其实就是全虚基类。
在Java中你可以如下定义一个类似接口的东西,暂也叫“接口”吧。(功能如同接下来引出的接口)
abstract class Demo { abstract void method1(); abstract void method2(); … }
(
注:纯虚函数和虚函数的区别,没有兴趣的可以略过这个注解。在Java中,只要包含一个纯虚函数,那么该类就叫做抽象类,用abstract修饰。纯虚函数就是没有函数体的函数,如method1和method2,纯虚函数同样需要abstract修饰。Java中其实没有虚函数的概念,C++中虚函数的目的是支持多态,而Java中普通函数就可以被动态绑定所以无需虚函数。总的来说,虚函数是为了多态,而纯虚函数是为了使该类不可实例化。
)
这个抽象类也可以有普通成员,普通函数等,如下
abstract class Demo { abstract void method1(); abstract void method2();
private int a;
void method3(){};//普通函数,有函数体
… }
为了某些我也没仔细想的原因,Java决定对上面的抽象类进行更好的剥离,新造了一个关键词叫interface,强制要求里面不能有普通成员变量,也不能具有非纯虚函数。于是上面这个类就会被剥离成
class Demo {
private int a;
void method3(){};
...
}
和一个接口
interface {
void method1();
void method2();
}
需要指出的是由于强制规定了interface的要求,所以我们不需要再写abstract interface或abstract void method1()了。
Java中的接口一般用于描述有共同行为的方法。
(注:Java中的接口有点相当于C++的虚基类,C++支持多重继承,为了防止出现多基类有共同方法导致不确定问题,于是C++创造了虚基类的概念,所以C++的虚基类的出现时为了消除多重继承带来的不确定问题,而由于Java不允许多重继承,因此也没有虚基类的概念。)
最后简单的介绍下Java的接口对象(类似C++的函数指针)的使用。
首先定义接口(这个例子来自http://www.cnblogs.com/warioland/archive/2012/01/30/2332203.html)interface
Computerable
{
public
double
area();
}
然后定义一个类,实现该接口
class
Rec
implements
Computerable
{
double
a,b;
Rec(
double
a,
double
b)
{
this
.a = a;
this
.b = b;
}
public
double
area() {
return
(a*b);
}
}
准备工作结束,接下来就可以定义一个接口对象:
Computerable bottom =
null
;
然后绑定对象
bottom =
new
Rec(
3
,
6
);
最后就可以调用接口里的方法了
System.out.println(
"矩形的面积是:"
+bottom.area());