如何扩展由另一个类实例化的java类?
鉴于两个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来调用父类的对象相应的方法)
这听起来像你最喜欢的是修改原来的A
和B
的行为。在这种情况下,您可以尝试扩展这两个类(其中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。我改变了上面的代码来说明我的意思。
这通常是通过代理完成。
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)来截获他们感兴趣的方法调用。
严格来说,这更像是一个装饰器而不是代理器。 http://en.wikipedia.org/wiki/Decorator_pattern – 2009-04-30 01:01:53
如果你需要引用A的私人领域或方法会怎样? – 2009-04-30 02:30:04
您可以创建一个包装,SubA
具有一个构造函数以A
为参数。
像这样:
SubA mySubA = new SubA(B.createA());
由于SubA
所有实例都是A
情况,然后你可以将其分配给现有的A
变量,并覆盖任何必要的方法。
A myA = new SubA(B.createA());
我想不出任何其他干净的做法。
如果你只是想添加一个字段到A
没有面向对象,如改变行为,你可以将它添加为“外部字段”。使用WeakHashMap
从A
的实例映射到字段值(只是只要字段值不直接或间接地引用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库中!
对于我在我的问题中给出的有限信息,这绝对是对它的回答。我将不得不做一些挖掘和一些实验,看看它是否在我所处的真实情况下工作,但我很肯定这个答案! – Scott 2009-04-30 23:58:39