随笔-72  评论-20  文章-0  trackbacks-1
1.接口回调是什么[2]
接口回调是指:可以把使用某一接口的类创建的对象的引用赋给该接口声明的接口变量,那么该接口变量就可以调用被类实现的接口的方法。实际上,当接口变量调用被类实现的接口中的方法时,就是通知相应的对象调用接口的方法,这一过程称为对象功能的接口回调。看下面示例。
interface People{
   void peopleList();
}
class Student implements People{
   public void peopleList(){
    System.out.println("I’m a student.");
}
}
class Teacher implements People{
  public void peopleList(){
    System.out.println("I’m a teacher.");
}
}
public class Example{
  public static void main(String args[]){
    People a;             //声明接口变量
a=new Student();      //实例化,接口变量中存放对象的引用
a.peopleList();        //接口回调
a=new Teacher();     //实例化,接口变量中存放对象的引用
a.peopleList();       //接口回调
}
}
结果:
I’m a student.
I’m a teacher.
再来看看向上转型(upcasting)的概念。
 
2.什么是向上转型[1]
Shape s=new Circle();
这里,创建了一个Circle对象,并把得到的引用立即赋值给Shape。通过继承,Circle就是一种Shape。
假设你调用基类方法(它已在导出类中被覆盖):
s.draw();
由于后期绑定(多态),将会正确调用Circle.draw()方法。
 
3.向上转型与接口回调的区别
看似向上转型和接口回调是一回事。看下面两句话,均出自Thinking in Java
使用接口的核心原因:为了能够向上转型为多个基类型[1]。即利用接口的多实现,可向上转型为多个接口基类型(具体见《抽象与接口》章节6)。
从实现了某接口的对象,得到对此接口的引用,与向上转型为这个对象的基类,实质上效果是一样的。(此句摘自Thinking in Java 3rd 接口与内部类一章)
所以,我认为,这两个概念是从两个方面来解释一个行为。接口回调的概念,强调使用接口来实现回调对象方法使用权的功能(下一章节详细分析)。而向上转型则牵涉到多态和运行期绑定的范畴。
 
4.用 Java 接口实现回调函数的等价功能
熟悉 MS-Windows X Window System 事件驱动编程模型的开发人员,习惯于传递在某种事件发生时调用(即回调)的函数指针。Java 的面向对象模型目前并不支持方法指针,Java 的接口支持提供了一种获得回调的等价功能的机制。其技巧就是:定义一个简单接口,并在该接口中声明我们要调用的方法。
假定我们希望在某个事件发生时得到通知。我们可以定义一个接口:
InterestingEvent.java
package org.zj.sample;
public interface InterestingEvent {
    public void interestingEvent ();
}
这使得我们可以控制实现该接口的类的任何对象。因此,我们不必关心任何外部类型信息。
发出事件信号的类必须等待实现了 InterestingEvent 接口的对象,并在适当时候调用 interestingEvent() 方法。
EventNotifier.java
package org.zj.sample;
public class EventNotifier {
    private InterestingEvent ie;
    private boolean somethingHappened;
 
    public EventNotifier(InterestingEvent event) {
         ie = event; // 保存事件对象以备后用。
         somethingHappened = false; // 还没有要报告的事件。
    }
 
    public void doWork() {
         if (somethingHappened) { // 检查设置的谓词。
           ie.interestingEvent();// 通过调用接口的这个方法发出事件信号。
         }
    }
   
    public void setHappened(){//设置谓词。
         somethingHappened=true;
    }
}
在上例中,使用 somethingHappened 谓词来跟踪是否应触发事件。希望接收事件通知的代码必须实现 InterestingEvent 接口,并将自身引用传递给事件通知程序。
CallMe.java
package org.zj.sample;
public class CallMe implements InterestingEvent {
    @SuppressWarnings("unused")
    private EventNotifier en;
 
    public CallMe() {
         // 注意 EventNotifier (InterestingEvent event),应该传递一个接口类型。
         // 而下面将this,即实现了InterestingEvent接口的CallMe实例传递给
//EventNotifier。也就是所谓的接口回调了。
         en = new EventNotifier(this); // 创建事件通知程序,并将自身引用传递给它。
    }
 
    // 为事件定义实际的处理程序。
    public void interestingEvent() {
              System.out.println("Call me Hello.");
    }
}
下面写个测试类。
Test.java
package org.zj.sample;
public class Test {
    public static void main(String[] args) {
         EventNotifier en=new EventNotifier(new CallMe());
         en.setHappened();
         en.doWork();
    }
}
 
结果:
Call me Hello.
 
5.参考资料
[1]Thinking in Java 3rd
[2]耿祥义,Java实用教程,清华大学出版社
[3] John D. MitchellJava 接口实现回调函数的等价功能,IBMDeveloper网站

posted on 2007-08-19 14:05 前方的路 阅读(9546) 评论(4)  编辑  收藏 所属分类: Java技术

评论:
# re: 什么是接口回调? 2008-08-07 01:41 | freedoom
写得真的很好,吸收了,多谢LZ。  回复  更多评论
  
# re: 什么是接口回调? 2011-03-12 16:37 | zhanliqing
例子有点像观察者模式  回复  更多评论
  
# re: 什么是接口回调?[未登录] 2011-05-05 08:49 |
怎么感觉类CallMe中的构造方法没有任何意义 因为根本无法向外部传递信息任何人消息  回复  更多评论
  
# re: 什么是接口回调? 2011-05-06 01:19 | kenma143
这个问题我也想了好久 想不明白这个构造函数的意思和运行方式
最后身体力行 编译运行了一遍 然后把CallMe的构造函数内容删了 然后再编译运行了一遍 发现没有问题
所以我觉得 这里作者错了 这里的确运用了 接口调用 但不是这一句
en = new EventNotifier(this);
而是这一句
EventNotifier en=new EventNotifier(new CallMe());
如果有错,请指出。  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: