`
kapok_fly
  • 浏览: 34535 次
最近访客 更多访客>>
社区版块
存档分类
最新评论

IAdaptable是什么?

阅读更多

[八进制]翻译原文地址: 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 笨笨注: 这里应的ArrayList应该是一个实现了IAdaptable接口的自定义类, 这个类'兼容'java.util.List
List list = (List)adaptable.getAdapter(java.util.List.class);

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

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

 

IAdaptable adaptable = new HashMap();//译注:这里的HashMap应该不是指java.util.HashMap  笨笨注: 这里应的HashMap应该是一个实现了IAdaptable接口的自定义类, 这个类'兼容'java.util.List
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 StringEntry>
  
<Entry>Second StringEntry>
  
<Entry>Third StringEntry>
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的类库.

分享到:
评论

相关推荐

    IJavaProject、IJavaElement、IAdaptable的作用域

    NULL 博文链接:https://primeton-livemail-tw.iteye.com/blog/1054950

    (更新至2022年)城镇男性就业人员调查周平均工作时间.xls

    数据来源:中国人口与就业统计NJ-2023版

    各地区技工院校综合情况(2022年).xls

    数据来源:中国劳动统计NJ-2023版

    基于matlab实现样本熵算法,可用于提取生理信号的特征参数

    基于matlab实现样本熵算法,可用于提取生理信号的特征参数,运算速度较快,m=1或2;r=0.1_std(data)~0.25_std(data)最佳。.rar

    蜂网-SCM车销访销业务.pptx

    蜂网_SCM车销访销业务.pptx

    数据更新至2020年国民经济主要指标一览表.xls

    数据来源:中国电力统计NJ-2021版

    图书借阅管理系统设计与实现及论大学生写作能力.docx

    图书借阅管理系统设计与实现及论大学生写作能力.docx

    node-v10.19.0-linux-armv6l.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    商品零售价格分类指数(2022年)(上年=100).xls

    数据来源:中国劳动统计NJ-2023版

    数据更新至2020年电网建设 本年开工规模.xls

    数据来源:中国电力统计NJ-2021版

    基于数据服务的信息需求管理系统设计与实现.docx

    基于数据服务的信息需求管理系统设计与实现.docx

    基于matlab实现的多个无人机的群飞行仿真 多个无人机的群飞行仿真.rar

    基于matlab实现的多个无人机的群飞行仿真 多个无人机的群飞行仿真.rar

    #-001-mysql-快递管理系统ssm(毕设和论文)

    随着物流行业信息化的深入使得物流过程中货物的状态和变化透明化,现代信息化的接入使得物流成本和费用的更容易被掌握,从而增强了信息的准确性。与此同时动态信息能够被及时掌握,根据实际情况做出快速而有效的反应,实现物流运作的动态决策。信息的及时、全面的获取与加工,供需双方可以充分的信息共享与沟通,使得物流服务更准确、从而提高客户的满意度;同时顾客可以有更多自我服务功能,可以随意定义自己的定制的物流服务;另外在提供物流服务的同时,可以为顾客提供信息、资金等双赢的增值服务。 该系统用spring mvc和MySQL实现了快递管理系统。快递管理系统有着很好的应用前景,随着计算机技术和网络技术的发展,它的功能将会得到不断的发展和完善。本系统可以根据实际应用的具体情况,适当加以修改,以便更好应用。本系统操作简单,灵活性好,系统安全性高,运行稳定。本文详细介绍了快递管理系统开发和设计的全过程。

    各地区分行业其他单位就业人员和工资总额(2022年).xls

    数据来源:中国劳动统计NJ-2023版

    node-v11.14.0-darwin-x64.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    基于VB实现的医疗纠纷检索系统设计(源代码+系统).zip

    【作品名称】:基于VB实现的医疗纠纷检索系统设计(源代码+系统) 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。

    数据更新至2020年分布式太阳能发电情况.xls

    数据来源:中国电力统计NJ-2021版

    node-v11.3.0-linux-arm64.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    农村居民分地区人均可支配收入来源(2022年).xls

    数据来源:中国劳动统计NJ-2023版

    tensorflow-rocm-2.13.1.600-cp39-cp39-manylinux2014-x86-64.whl

    cnn

Global site tag (gtag.js) - Google Analytics