Eclipse中的IAdaptable分析

來源:互聯網
上載者:User
  Java是一種強型別語言,每個執行個體都必須有指定的類型。實際上,Java類型有兩種宣告類型和 運行時類型 (也可以相應的說是靜態類型 和動態類型 ). 像Python這樣的弱類型語言通常稱為無類型,但是這樣說並不嚴謹,因為每個執行個體都有它的運行時類型。你只是不用事先聲明一個執行個體的類型而已。

  要想調用一個對象中的方法,這個方法需要在宣告類型中存在。也就是說,你只能調用定義在父類中的方法,即使該執行個體是一個確定的子類型:

List list = new ArrayList();
list.add("data"); // 在這裡沒問題
list.ensureCapacity(4); // 這裡就不行了ensureCapacity() 只在ArrayList中才有。
  如果我們要調用實際類型中的方法,我們首先要將它轉為正確的類型。在本例中,我們可以把 ArrayList 轉為List,因為ArrayList實現了List 介面. 也可以在運行時動態檢驗,使用 list instanceof ArrayList.

   可擴充的介面

  糟糕的是,一個類不能總是實現你所需要實現的介面。可能是因為這隻對少數幾種情況才有效,或者它是一個沒有被關聯的庫中的類型,或者這個介面在後期又被改變了。

  這種情況就可以使用IAdaptable。 你可以把 IAdaptable 動態進行類型轉化。使用如下方法避免直接的類型轉化:

Object o = new ArrayList();
List list = (List)o;
  我們可以這樣做:

IAdaptable adaptable = new ArrayList();
List list = (List)adaptable.getAdapter(java.util.List.class);
  你可認為它是一種類型動態轉化; 我們把adaptable轉為List執行個體。

  為什麼不直接轉化,而要用額外的getAdapter() 呢?這種機制可以使我們將目標類轉化為沒有實現的介面。例如, 我們可能想使用HashMap 作為一個 List, 儘管他們並不相容。

IAdaptable adaptable = new 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;
 }
 // ...
}


  返回的是一個對自身的代理,而不是直接轉化類型。如果請求的是不支援的類型,可以直接返回null表明失敗,這樣比拋出異常要好。

  PlatformObject

  當你想添加新的要擴充的類型時,只是簡單的修改一下就可以了。在任何情況下,如果已經得到了類型,為什麼不修改介面?不修改類(如果使用介面,不容易保證向後相容)或者改變它的類型(HashMap不是 List,但是可以轉化)是有原因的。要解決這個問題,在Eclipse中,使用了一個抽象類別 PlatformObject。它為你實現了 IAdaptable介面,你就可以不用再操心了。

  PlatformObject 代理所有的它對getAdapter()的請求到 IAdapterManager. IAdapterManager是平台預設提供的,通過 Platform.getAdapterManager()來訪問。你可以將它想象為一個巨大的 Map ,它負責關聯類別和適當的適配器。PlatformObject的 getAdapter() 方法可以訪問到這個Map.

  適配已存在的類

  這樣的好處是可以為每一個PlatformObject對象動態關聯新的適配器,而不用重新編譯。在Eclipse中的很多地方都是這樣來支援擴充的。

  這裡希望將裝有String的List轉為XML節點。 XML節點顯示為:

<List>
<Entry>First String</Entry>
<Entry>Second String</Entry>
<Entry>Third String</Entry>
</List>
  因為List的toString方法可能有別的用途,所以不能使用。 可以為List添加一個工廠,當有轉為XML節點的請求時,一個Node對象就會自動返回。

  這裡需要3個步驟:

  1. 從List中產生Node

  使用IAdapterFactory 來封裝轉換機制:

import nu.xom.*;
public class NodeListFactory implements IAdapterFactory {
 /** The supported types that we can adapt to */
 private static final Class[] types = {
  Node.class,
 };
 public Class[] getAdapterList() {
  return types;
 }
 /** The actual conversion to a 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為我們管理IAdapterManager ,而且註冊過程相當簡單:

Platform.getAdapterManager().registerAdapters(
new NodeListFactory(), List.class
);
  上面的代碼要求平台管理者關聯NodeListFactory和List。但我們要求List執行個體的適配器,它會調用這個工廠。根據我們對工廠的定義,會獲得一個Node對象。在Eclispe中,這一步必須在外掛程式啟動的時候顯式的執行,要隱式執行可以通過 org.eclipse.core.runtime.adapters 擴充點。

  3. 向List要求Node

  這裡是要求適配器返回一個 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 外掛程式中的使用。在這些例子中, IPropertySource 在UI外掛程式中,它需要與非UI外掛程式的資料相關聯。當UI外掛程式初始化時,它註冊IPropertySource 到Platform, 當資料對象在瀏覽器中被選中時,屬性視圖中就會顯示相應的屬性。

  很明顯, java.util.List不能擴充PlatformObject, 所以你不能指望例子中的代碼能夠編譯通過,你可以重新構造 List的子類來實現目的.繼承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();
 }
 // ...
}
  本例中使用了XOM 來產生XML。

相關文章

Beyond APAC's No.1 Cloud

19.6% IaaS Market Share in Asia Pacific - Gartner IT Service report, 2018

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。