新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论Java, J2SE, J2ME, J2EE, 以及Eclipse, NetBeans, JBuilder等Java开发环境,还有JSP, JavaServlet, JavaBean, EJB以及struts, hibernate, spring, webwork2, Java 3D, JOGL等相关技术。
    [返回] 中文XML论坛 - 专业的XML技术讨论区计算机技术与应用『 Java/Eclipse 』 → [转帖]IAdaptable 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 4136 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: [转帖]IAdaptable 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     hongjunli 帅哥哟,离线,有人找我吗?魔羯座1978-1-20
      
      
      威望:5
      头衔:为振兴论坛而努力!
      等级:研二(中了一篇WWWC Poster)(版主)
      文章:808
      积分:7964
      门派:IEEE.ORG.CN
      注册:2006/3/9

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给hongjunli发送一个短消息 把hongjunli加入好友 查看hongjunli的个人资料 搜索hongjunli在『 Java/Eclipse 』的所有贴子 引用回复这个贴子 回复这个贴子 查看hongjunli的博客楼主
    发贴心情 [转帖]IAdaptable

    From:http://bjzhanghao.cnblogs.com/archive/2005/09/24/243312.html

    原文地址:http://www.eclipsezone.com/articles/what-is-iadaptable/

    IAdaptable在Eclipse里是一个非常重要的接口。对于Eclipse开发老手来说,它就像异常处理和抽象类一样寻常;但是对新手而言,它却令人感到困惑和畏惧。这篇文章将向你解释IAdaptable到底是什么,以及它在Eclipse里起到的作用。
    类型转换

    Java是所谓的强类型语言,也就是说,每个实例都对应一个类型。其实类型分为两种:声明类型和运行时类型(也分别被称为静态类型和动态类型)。像 Python这样的弱类型语言常被称为无类型的语言,其实严格说来不是这样,因为每个实例都对应一个运行时类型,只是你并不需要声明这一点而已。

    现在回到Java,为了能够执行一个类的某个方法,这个方法必须在声明类型中可见,换句话说,即使在运行时实例是某个子类型,你也只能执行那些父类型里定义的方法。

    List list = new ArrayList();
    list.add("data");       // 正确,add是List里定义的方法
    list.ensureCapacity(4); // 不正确,ensureCapacity()只在ArrayList被定义

    如果一定要执行特定类型的方法,我们必须先强制转换这个实例到正确的类型。对于上面的例子,我们可以将list转换为ArrayList(译注:原文In this case, we can cast ArrayList to List,怀疑是笔误),因为ArrayList实现了List接口,你甚至可以在运行时通过instanceof关键字检验list是否为 ArrayList的一个实例。
    可扩展的接口

    不幸的是,一个类可能并没有实现你需要的接口,这样就无法进行强制类型转换了。原因有很多,比如只在少数情况下才需要这个接口,或者你需要的接口是在另一个不相关的库里,又或者接口是有了类以后才开发出来的,等等。

    这时你就需要IAdaptable了。可以把IAdaptable想象为一个能够动态进行类型转换的途径。对比下面的直接类型转换:

    Object o = new ArrayList();
    List list = (List)o;

    换一种方式,我们可以这样做:

    IAdaptable adaptable = new ArrayList();//译注:这里的ArrayList应该不是指java.util.ArrayList
    List list = (List)adaptable.getAdapter(java.util.List.class);

    这就是上面所说的动态类型转换,我们所做的事情是试图把adaptable转换为一个List实例。

    那么,当可以直接转换的时候为什么要费这个力气通过getAdapter()来转换呢?其实这种机制可以让我们将目标类转换为它并没有实现的接口。举个例子,我们可能想把一个HashMap当作List来用,尽管这两个类的性质并不相同,可以这么做:

    IAdaptable adaptable = new HashMap();//译注:这里的HashMap应该不是指java.util.HashMap
    List list = (List)adaptable.getAdapter(java.util.List.class);
    实现IAdaptable接口

    大部分IAdaptable的实现是一些if语句的叠加,比如我们现在要实现HashMap的getAdapter()方法,它看起来可能是这样:

    public class HashMap implements IAdaptable {
      public Object getAdapter(Class clazz) {
        if (clazz == java.util.List.class) {
          List list = new ArrayList(this.size());
          list.addAll(this.values());
          return list;
        }
        return null;
      }
      //
    }

    所做的就是返回一个适配器(adapter,更确切的说是一个副本),而不是进行直接的类型转换。如果参数类型没有被支持,惯例是返回null值(而非抛出异常),代表这个方法失败了。因此,在调用这个方法时,不应该假定它总是返回非null值。
    PlatformObject

    当然,如果你希望增加一个新的被支持的adapter类型时必须编辑这个类才行(译注:在getAdapter()里增加更多的if语句),这会比较辛苦。而且,既然你已经知道了这个类型,何不直接修改接口声明呢?其实有很多原因使得你并不希望直接编辑这个类(例如更容易保持向下兼容性),也不想改变它的类型(HashMap虽然不是一个List,但可以转换过去)。

    Eclipse通过PlatformObject抽象类来解决以上问题,它为你实现了IAdaptable接口,Eclipse平台(Platform)提供了IAdapterManager的一个实现,并且可以通过Platform.getAdapterManager()访问到,它把所有对getAdapter()的请求(调用)委托给一个名为IAdapterManager的东西。你可以将它想象为一个巨大的保存着类和 adapter信息的Map,而PlatformObject的getAdapter()方法会查找这个Map。
    适配已存在的类

    这样,PlatformObject不需要重新编译就能够支持新的adapter类型,这一点在Eclipse里被大量使用以支持workspace的扩展点。

    现在假设我们想要将一个只包含String类型元素的List转换为一个XMl节点,这个节点的格式如下:

    <List>
      <Entry>First String</Entry>
      <Entry>Second String</Entry>
      <Entry>Third String</Entry>
    </List>

    因为toString()方法可能有其他用途,我们不能通过覆盖toString()方法来实现这个功能。所以,我们要给List关联一个工厂类以处理XML节点类型的适配请求。要管理工厂类需要以下三个步骤:

    1、由List生成一个Node,我们把这个转换过程用IAdapterFactory包装起来:

    import nu.xom.*;
    public class NodeListFactory implements IAdapterFactory {
      /**//* 可以转换到的类型 */
      private static final Class[] types = {
        Node.class,
      };
      public Class[] getAdapterList() {
        return types;
      }
      /**//* 转换到Node的功能代码 */
      public Object getAdapter(Object list, Class clazz) {
        if (clazz == Node.class && list instanceof List) {
          Element root = new Element("List");
          Iterator it = list.iterator();
          while(it.hasNext()) {
            Element item = new Element("Entry");
            item.appendChild(it.next().toString());
            root.appendChild(item);
          }
          return root;
        } else {
          return null;
        }
      }
    }

    2、把这个工厂类注册到Platform的AdapterManager,这样当我们希望从List的实例中获得一个Node实例时,就会找到我们的工厂类。注册一个工厂类的方式也很简单:

    Platform.getAdapterManager().registerAdapters(
      new NodeListFactory(), List.class
    );

    这条语句将NodeListFactory关联到List类型。当从List里请求adapter时,Platform的 AdapterManager会找到NodeListFactory,因为在后者的getAdapterList()方法的返回结果里包含了Node类,所以它知道从List实例得到一个Node实例是可行的。在Eclipse里,这个注册步骤一般是在plugin启动时完成的,但也可以通过 org.eclipse.core.runtime.adapters扩展点来完成。

    3、从List获得Node,下面是例子代码:

    Node getNodeFrom(IAdaptable list) {
      Object adaptable = list.getAdapter(Node.class);
      if (adaptable != null) {
        Node node = (Node)adaptable;
        return node;
      }
      return null;
    }
    总结

    综上所述,要在运行时为一个已有的类增加功能,所要做的只是定义一个用来转换的工厂类,然后把它注册到Platform的 AdapterManager即可。这种方式在保持UI组件和非UI组件的分离方面特别有用。例如在org.rcpapps.rcpnews.ui和 org.rcpapps.rcpnews这两个plugin里,前者的IPropertySource需要与后者的数据对象(data object)相关联,当前者初始化时,它将IPropertySource注册到Platform,当数据对象在导航器(navigator)里被选中的时候,属性视图里就会显示正确的属性。

    显然,java.util.List并不是PlatformObject的子类,所以如果你希望能够编译这里所说的例子,必须建立一个List的子类型。注意,可以直接实现IAdaptable接口,而非必须继承PlatformObject抽象类。

    public class AdaptableList implements IAdaptable, List {
      public Object getAdapter(Class adapter) {
         return Platform.getAdapterManager().getAdapter(this, adapter);
      }
      private List delegate = new ArrayList();
      public int size() {
        return delegate.size();
      }
      //
    }

    最后,例子里生成XML的部分使用了XOM的类库.
    posted on 2005-09-24 16:26 八进制 阅读(2320) 评论(6)  编辑 收藏 引用 网摘 所属分类: Eclipse

    评论
    # re: [翻译]IAdaptable是什么? 2005-09-26 21:48 tutufool
    好文,正好要用到IAdaptable来进行editor和view的通信
    弱弱的问一个问题,如何得到当前view的窗口尺寸?
    谢拉  回复  更多评论
      

    # re: [翻译]IAdaptable是什么? 2005-09-27 21:55 RAY
    你好,看了你的文章,十分佩服,小弟有一个JSP的问题想请教一下,希望您能抽点时间帮助看一下,该页面处理上一个页面的表单传过来的数据判断后存储到数据库中,问题是,当弹出脚本的确认对话框后,即使用户没有进行选择,下面的JSP代码仍然继续执行,将数据存储到库中,我不知道是什么原因,希望您能给些建议,和修改的方法。代码如下:

    <%@ page contentType="text/html; charset=gb2312" language="java" import="java.sql.*" %>
    <%@ page import="java.util.*" %>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
    <title>无标题文档</title>
    </head>


    <body>


    <jsp:useBean id="db" scope="page" class="xt.DBConnect"/>

    <% try{

    String cUserID=request.getParameter("cUserID");
    String vUserName=request.getParameter("vUserName");
    String vUserPwd=request.getParameter("vUserPwd");
    String cUserLevel_c=request.getParameter("cUserLevel_c");
    String vCommName=request.getParameter("vCommName");
    String dBuildTime=request.getParameter("dBuildTime");

    ResultSet rs1=db.executeQuery("select vCommID from t_b_committe where vCommName='"+vCommName+"'");
    rs1.next();
    String vCommID=rs1.getString(1);


    ResultSet rs2=db.executeQuery("select cUserID from t_b_user where cUserID='"+cUserID+"'");

    if(rs2.next())
    {


    %>

    <script language="javascript">
    var truthBeTold = window.confirm("该用户ID已经存在,单击“确定”系统将仍然使用原ID,并将您所选择控制的党组织添加到原ID所控制的党组织范围内,单击“取消”返回。");
    if (truthBeTold==false)
    {
    window.location.href='admin_add.jsp';
    }
    </script>

    <%

    String sql1="insert into t_b_user_comm values ('"+cUserID+"','"+vCommID+"')";
    db.executeUpdate(sql1);
    rs1.close();
    rs2.close();
    db.destroy();
    %>
    <script language="javascript">
    window.location.href='manager_info.jsp';
    </script>
    <%
    }else
    {
    String sql2="insert into t_b_user values ('"+cUserID+"','"+vUserName+"','"+vUserPwd+"','"+cUserLevel_c+"','"+dBuildTime+"')";
    String sql3="insert into t_b_user_comm values ('"+cUserID+"','"+vCommID+"')";
    db.executeUpdate(sql2);
    db.executeUpdate(sql3);
    rs1.close();
    rs2.close();
    db.destroy();
    response.sendRedirect("manager_info.jsp");

    }


    }
    catch(Exception e)
    {
    System.out.println("Exception:----"+e);
    }

    %>

    </body>
    </html>


       收藏   分享  
    顶(0)
      




    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2007/3/25 9:41:00
     
     GoogleAdSense魔羯座1978-1-20
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 Java/Eclipse 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/12/22 8:00:50

    本主题贴数1,分页: [1]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    5,609.375ms