12.10 使用案例
使用泛型可以处理程序中会遇到的并行继承层次结构(parallel inheritance hierarchy)的问题。在并行继承层次结构中包含两组互相对应的类,其中一组类中两个类之间的继承关系也意味着另外一组类中的对应类之间也存在继承关系。比如,在一个用户界面组件库中,组件的抽象表示和实际的渲染逻辑通常是分开的,由不同的类来表示。每个组件类都有对应的进行渲染的类。如果一个组件类是另外一个组件类的子类,那么该组件对应的渲染类同时也是另外的组件对应的渲染类的子类。
代码清单12-37给出了一般的实现方式。Component类是所有组件的父类,ComponentRenderer类是所有进行组件渲染的类的父类。ComponentRenderer类中的render方法用来对组件进行渲染操作。表示按钮的Button类继承自Component类,同时Button类对应的进行渲染的类ButtonRenderer也继承自ComponentRenderer类。在ButtonRenderer类的render方法实现中,由于参数类型是Component类,因此需要对参数对象的实际类型进行判断,以避免对错误类型的对象进行操作。在调用ButtonRenderer类的方法时,可以传递同样继承自Component类的Label类的对象作为参数。这在编译时是正确的,而运行时会出现错误。
代码清单12-37 不使用泛型的并行继承层次结构的实现示例
abstract class Component{
}
abstract class ComponentRenderer{
abstract void render(Component window);
}
class Button extends Component{
}
class Label extends Component{
}
class ButtonRenderer extends ComponentRenderer{
void render(Component window){
if(window instanceof Button){
//界面渲染
}
else{
throw new IllegalArgumentException();
}
}
}
public class NormalComponent{
public void render(){
ButtonRenderer renderer=new ButtonRenderer();
renderer.render(new Button());
renderer.render(new Label());//编译正确,运行时错误
}
}
使用泛型可以限制方法调用时所接收的参数的类型,从而避免这个问题。代码清单12-38给出了使用泛型之后的实现方式。新的ButtonRenderer类的render方法只能使用Button类的对象作为参数,这就避免了使用错误类型的对象来调用此方法。类型检查在编译时完成,可以及早地发现问题。
代码清单12-38 使用泛型的并行继承层次结构的实现示例
abstract class Component{
}
abstract class ComponentRenderer<C extends Component>{
abstract void render(C component);
}
class Button extends Component{
}
class ButtonRenderer extends ComponentRenderer<Button>{
void render(Button button){
//界面渲染
}
}
public class GenericComponent{
public void render(){
ButtonRenderer renderer=new ButtonRenderer();
renderer.render(new Button());
}
}