2009-12-06 55 views
2

我有許多不同的表示同一種對象;讓我們把它稱爲一件事。 「事」是一個標記界面。 ThingFormat0,ThingFormat1,ThingFormat2等都是實現Thing的JavaBean。 (因爲它們是JavaBeans,所以JSON編組會自動將它們自動轉換爲JSON或從JSON自動轉換它們。)ThingFormat1只有一些成員,如名稱和標識。 ThingFormat2有與其他東西的URI鏈接。在ThingFormat3中有ThingFormat1表示那些其他東西等。繼承最終的類;或者,一個退化裝飾器

JSON序列化程序知道如何自動轉換URI。 (它適用於任何可以使用toString()和構造函數ClassName(String string)進行轉換的類。)

我想要一個ThingFormat0,它的行爲像一個URI,但實現了標記接口Thing。

public class ThingFormat0 extends URI implements Thing {} 

這不起作用,因爲URI是最後一個類,不能被子類化。

我能想到做到這一點的唯一方法是製作一個裝飾器(一種非常簡單的修飾器,因爲它不會向URI添加任何功能)。這在一些「duck-typed」語言中很容易,但在Java中更加痛苦,因爲我必須包裝一個URI並實現我需要的所有URI方法。有更容易的方法嗎?

回答

3

兩種簡單的方法我能想到的:

  • 如果你使用Eclipse,你可以有自動生成的任何領域的委託方法。
  • 將URI的源複製到名爲ThingURI的新類中。
1

你不能繼承最終的類。期。

在URI的情況下,由於安全原因,它幾乎肯定是最終的;即通過提供(例如)允許它破壞訪問控制的欺騙性的URI子類型來阻止某人破壞沙箱安全。

所以是的,你需要使用包裝或裝飾或類似的東西。

2

是否有任何理由類不能使用組合而不是繼承?

public class ThingFormat0 implements Thing { 
    private final URI uri; 

    public ThingFormat0(String uri) { this.uri = URI.create(uri); } 

    public ThingFormat0(URI uri) { this.uri = uri; } 

    public URI getUri() { return uri; } 

    @Override public String toString() { 
    return uri.toString(); 
    } 
} 
+0

當Thing是我的Response類的成員時,Response的JSON序列化是{「thing」:{「uri」:「http:// whatever」}}而不是{「thing」:「http://隨你」}。 – 2009-12-08 00:40:28

0
// base class that handles delegation 
class BaseThing implements Thing { 

    BaseThing(String uri) { ... } 

    BaseThing(URI uri) { ... } 

    URI getURI() { ... } 

    ... 
} 

class ThingFormat0 extends BaseThing { 
    ... 
} 
0

你發現這是困難的,因爲你的ThingFormat類型的URI。他們公開URI並且可以對應於URI,但是這不會使它們成爲URI。也許你在尋求實現繼承,但是接口繼承因爲這不是合適的is-a關係;它失敗了LSP

例如,考慮一個ThingFormat是否有方案或片段組件,或者是否可以針對某個基礎URI進行解析。這些都是URI的方面和操作,與ThingFormat無關,無論它發生什麼。