2009-04-30 156 views
2

鑑於兩個Java類,A和B,其中A通常是利用B實例化的,如:如何擴展由另一個類實例化的java類?

A myA = B.createA(); 

我可以創建一個(我們稱之爲蘇巴)一個子類,莫名其妙地就被實例化B.createA()方法?

(請注意,我不能修改A和B ....)

我知道,不是所有實例都蘇巴的情況,因此,我不能做到這一點:

SubA mySubA = B.createA(); 

同樣,我不能這樣做:

SubA mySubA = (SubA) (B.createA()); 

出於同樣的原因 - 它會得到一個ClassCastException。

我是密集的,忘記了一些根本性的東西,還是沒有辦法做到這一點? (後期補充:我非常抱歉,我應該提到A和B各有大約50種方法,我想要做的就是向SubA中添加一個屬性,以及一個getter和setter。我真的寧可不落實的的方法都50來調用父類的對象相應的方法)

回答

3

這聽起來像你最喜歡的是修改原來的AB的行爲。在這種情況下,您可以嘗試擴展這兩個類(其中B的擴展名純粹是爲了指定創建SubA的稍微不同的工廠方法)。

class SubA extends A { 
    /** This is the one special aspect of SubA justifying a sub-class. 
     Using double purely as an example. */ 
    private double specialProperty; 

    public double getSpecialProperty() { return specialProperty; } 
    public void setSpecialProperty(double newSP) { specialProperty = newSP; } 

    public SubA() { 
     super(); 
     // Important differences between SubAs and As go here.... 
     // If there aren't any others, you don't need this constructor. 
    } 

    // NOTE: you don't have to do anything else with the other methods of 
    // A. You just inherit those. 
} 

class SubB extends B { 
    // Purely for the purposes of a slightly different factory method 
    public A createA() { 
     return new SubA(); 
    } 

    // Or if you need a static method 
    // (this is usually instead of the first choice) 
    public static A createA() { 
     return new SubA(); 
    } 
} 

注意,在這一點上,你可以創建你SubB工廠對象之一,使它看起來像原來B像這樣:

B myNewB = new SubB(); 
A myA = myNewB.createA(); 

或者,如果您使用的是靜態工廠相反,它不是非常接近(但它很接近)。

A myA = SubB.createA(); 

現在,如果你真的需要做的子屬性的東西,你必須通過子接口訪問它。也就是說,如果您創建對象,像這樣:

SubA mySubA = SubB.createA(); 
mySubA.setSpecialProperty(3.14); 
double special = mySubA.getSpecialProperty(); 

編輯討論「後加」:

在這一點上,你的蘇巴對象應該是正是你想要的。它將繼承父(A)中的50個方法,並且可以將您的附加屬性添加到子項以及getter和setter。我改變了上面的代碼來說明我的意思。

+0

對於我在我的問題中給出的有限信息,這絕對是對它的回答。我將不得不做一些挖掘和一些實驗,看看它是否在我所處的真實情況下工作,但我很肯定這個答案! – Scott 2009-04-30 23:58:39

3

這通常是通過代理完成。

class SubA extends A { 
    private A proxiedClass; 

    public SubA(A a) { 
     proxiedClass = a; 
    } 

    public int anyMethodInA() { 
     return proxiedClass.anyMethodInA(); 
    } 
} 

...

SubA mySubA = new SubA(B.createA()); 

手動執行此操作相當冗長,因此大多數人使用某種類型的AOP庫(如AspectJ)來截獲他們感興趣的方法調用。

+0

嚴格來說,這更像是一個裝飾器而不是代理器。 http://en.wikipedia.org/wiki/Decorator_pattern – 2009-04-30 01:01:53

+0

如果你需要引用A的私人領域或方法會怎樣? – 2009-04-30 02:30:04

1

您可以創建一個包裝,SubA具有一個構造函數以A爲參數。

像這樣:

SubA mySubA = new SubA(B.createA()); 

由於SubA所有實例都是A情況,然後你可以將其分配給現有的A變量,並覆蓋任何必要的方法。

A myA = new SubA(B.createA()); 

我想不出任何其他乾淨的做法。

1

如果你只是想添加一個字段到A沒有面向對象,如改變行爲,你可以將它添加爲「外部字段」。使用WeakHashMapA的實例映射到字段值(只是只要字段值不直接或間接地引用A或者你有一個對象壽命爭的問題):

private static final Map<A,FieldType> map = 
    new java.util.WeakHashMap<A,FieldType>(); // thread-safe from 1.6, IIRC 

public static FieldType getField(A a) { 
    return map.get(a); 
} 
public static void setField(A a, FieldType value) { 
    map.set(a, value); 
} 

真的我們應該使用WeakIdentityHashMap,但它不存在於Java庫中!

相關問題