接口和继承
你第一次查看javax.print.attribute包里的接口和类时你也许会感到选择那些列表里的接口和类很麻烦。除了Attribute 和AttributeSet和继承AttributeSet的HashAttributeSet,javax.print.attribute包里有4个子接口和类,列出在表4和图1中。

Table 4. javax.print.attribute 里定义的接口和类
Figure 1. javax.print.attribute 包的一部分类的层次结构.
那么有了Attribute, AttributeSet, 和 HashAttributeSet为什么需要使用这些不同的接口和继承类呢?是因为这些特殊的类是为那些特殊的属性量身定做的。比方说,我提到过当你创建打印文档的时候有个地方可以使用的属性例如ColorSupported那里不能使用。当创建这样的文档,你可以使用DocAttributeSet接口(或者更专业一点,HashDocAttributeSet这个继承的类),这个继承类只允许你添加继承DocAttribute这个接口的属性。这四种不同的模块如下:
·Doc: 在创建文档时指定如何打印文档
·PrintJob: 打印任务的属性描述任务的状态
·PrintRequest: 初始化打印时传给任务的请求
·PrintService:由打印服务返回来描述打印机的功能
要知道如何工作,我们来创建一个DocAttributeSet的实例然后为AttributeSet设置DocAttributeSet和OrientationRequested属性。HashDocAttributeSet定义了很好的结构,所有你可以很简便的如下创建实例:
attrs.add(OrientationRequested.PORTRAIT);
attrs.add(OrientationRequested.PORTRAIT);
attrs.add(ColorSupported.SUPPORTED);
要学习怎么运行,记住每一个AttributeSet子接口都有一个相应Attribute子接口和继承子类。当添加一个属性时,继承的子类试图把Attribute作为参数给相应的子接口,这样来确保只有当前适当的属性会成功添加。
这样的话,HashDocAttributeSet 的add方法第一次和OrientationRequested的一个实例一起调用,并成功的把它作为一个object传给DocAttribute。因为如图2所示,OrientationRequested继承了那个接口。与之相对应,传ColorSupported实例的时候因为没有继承DocAttribute所以失败了。

Figure 2. javax.print.attribute 包的一部分类的层次结构
AttributeSet and HashAttributeSet
你已经知道了为什么会有四个子类,但是AttributeSet接口和HashAttributeSet父类又是什么呢?AttributeSet/HashAttributeSet在你不能确定要存储在这个集合中的那些仅仅和一个模块相关的属性时使用。记得我以前提到的lookupPrintServices()方法允许你指定AttributeSet参数来限制返回的打印服务。表面上看来最好指定PrintServiceAttributeSet的实例,但是很多你可能用到的属性并不继承PrintServiceAttribute。
我们假设你想要让lookupPrintServices()方法返回支持彩色打印和风景画打印的打印机。这些属性与ColorSupported和OrientationRequested属性关联,但是请注意这些类并不共享模块,前者是一个PrintServiceAttribute而OrientationRequested与另外三个模块(Doc, PrintRequest,和 PrintJob)关联。这意味着不存在单个的AttributeSet接口或类来同时包含ColorSupported和Sides属性。
创建AttributeSet的方法使用一个HashAttributeSet实例同时包含一个OrientationRequested 和 ColorSupported太简单了。不像它的子类,它并不限制你往上加特殊的属性,所以可以用以下代码成功执行:
attrs.add(ColorSupported.SUPPORTED);
attrs.add(OrientationRequested.LANDSCAPE);
PrintService[] services = PrintServiceLookup.lookupPrintServices(null, attrs);
