说我在塑造梦想:
public interface Dream {
void start();
}
public class SimpleDream implements Dream {
// implementation here...
}
public class Inception implements Dream {
Dream inner;
// implementation here...
}
现在说我有这些梦想的装饰师课程:
public class Decorator implements Dream {
Dream decorated;
public void start() {
// do something else
decorated.start();
}
}
我希望能够编写一个方法,该方法将采用任何Dream
实例并使用Decorator
递归(字段)来修饰它。我能用反射编写这样的方法,但在尝试装饰Dream
子类型的字段时遇到了问题:
public class LucidDream implements Dream {
SimpleDream inner;
// implementation here...
}
我的通用方法会尝试设置一个新的Decorator
将SimpleDream
包裹到inner
的{{1}}字段中,然后执行此操作(使用LucidDream
)将抛出异常(Field.set
)。
我尝试使用代理,但它没有用。
P.S。
我实际上正在使用Scala,所以(a)原谅我的Java代码,(b)如果只有Scala可以实现这一点,我也想知道。
答案 0 :(得分:1)
不幸的是,你说你不能改变LucidDream.inner
class LucidDream implements Dream{
SimpleDream inner; // CANNOT be changed to "Dream"
}
在这种情况下,据我所知,生活变得更加复杂,唯一的解决方法是动态扩展SimpleDream ,使用字节码增强库,如cglib。 请参阅此处的讨论(忽略他们正在讨论抽象类的事实 - 主要是动态扩展类而不是接口):
然而,这不是微不足道的(这使得维护和代码部署变得复杂)所以我只有在我真的别无选择时才会求助于它,即我真的需要这种泛化水平,而且我真的无法&# 39; t改为"梦想内心" ....
答案 1 :(得分:0)
你是说这个吗?
public class DreamDecorator() implements Dream {
Dream decorated;
public DreamDecorator(Dream decorated) {
this.decorated = decorated;
}
public void start() {
// do something else
decorated.start();
}
}
public class LucidDream(Dream dream) implements Dream {
Dream dream;
public LucidDream(Dream dream) {
this.dream= dream;
}
}
你可以通过这个将装饰简单的梦想传递给清醒的梦想
new LucidDream(new DreamDecorator(new SimpleDream()))
或动态使用反射,例如:
Class<?> sdClazz = Class.forName(SimpleDream.class.getName());
Constructor<?> sdCtor = sdClazz.getConstructor();
SimpleDream sd = (SimpleDream) sdCtor.newInstance();
Class<?> ddClazz = Class.forName(DreamDecorator.class.getName());
Constructor<?> ddCtor = ddClazz.getConstructor(Dream.class);
DreamDecorator dd = (DreamDecorator) ddCtor.newInstance(new Object[] { sd });
Class<?> clazz = Class.forName(LucidDream.class.getName());
Constructor<?> ctor = clazz.getConstructor(Dream.class);
LucidDream lucidDream = (LucidDream) ctor.newInstance(new Object[] { dd});