我有一个通用类:
public class Facet<C extends Component>
{
private final C child;
public Facet(C child) { this.child = child; }
public C getChild() { return this.child; }
public UIComponent getViewComponent() {
return PrimeFacesComponentFactory.create(facesContext, this.getChild());
}
}
我有一个组件工厂也有一堆方法,其中几个看起来像这样:
public static UIComponent create(FacesContext fc, Component component) {
throw new UnsupportedOperationException("Method not yet implemented for class: " + component.getClass().getName());
}
public static UIRow create(FacesContext fc, Row modelRow) { ... }
public static UIColumn create(FacesContext fc, Column modelColumn) { ... }
注意:在每个工厂方法中,第二个参数是扩展Component的对象,返回的内容始终是UIComponent的子类。第一个工厂方法(抛出异常的方法)旨在成为“全部捕获”,如果没有为特定组件编写特定工厂方法,则会调用该方法。
我正在尝试做的事情:应根据组件facet的子类型调用正确的工厂方法。发生的事情是第一个工厂方法始终被调用(例如,抛出异常的方法)。这对我来说是违反直觉的,因为C的类型在运行时是已知的,C是“扩展Component的某种特定类型”。
调试,我在Facet#getViewComponent
设置一个断点,当我知道facet.getChild()
将返回Row类型的对象时调用它。所以在这个例子中C是Row。当我调用工厂方法时,我感到很惊讶,例如
PrimeFacesComponentFactory.create(facesContext, facet.getChild());
程序执行流向“catch all”工厂方法!但是,如果我按如下方式显式地转换facet.getChild():
PrimeFacesComponentFactory.create(facesContext, (Row)facet.getChild());
然后调用特定方法。很奇怪,因为我只是/冗余地将一行写入一行。
我读过some about why this is happening,但它仍然模糊不清并且违反我的想法。无论如何,我该如何解决这个问题?
答案 0 :(得分:3)
重载解析在编译时针对Facet
类发生一次,而不是C
中的每个Facet<C>
,而不是在运行时。一个潜在的解决方案是让你的全能方法变得更聪明:
public static UIComponent create(FacesContext fc, Component component) {
if (component instanceof Row)
return create(fc, (Row)component);
else if (component instanceof Column)
return create(fc, (Column)component);
// include other types, and lastly
else
throw new UnsupportedOperationException("Method not yet implemented for class: " + component.getClass().getName());
}
答案 1 :(得分:0)
使用以下声明
public C getChild() { return this.child; }
public UIComponent getViewComponent() {
return PrimeFacesComponentFactory.create(facesContext, facet.getChild());
}
假设facet
是this
,在编译时,对类型参数C
唯一了解的是它扩展了Component
。因此,编译器将此方法调用与声明为接受Component
的方法绑定。
public static UIComponent create(FacesContext fc, Component component) {
throw new UnsupportedOperationException("Method not yet implemented for class: " + component.getClass().getName());
}