诊断Java代码: “杀手组合”― mixin、Jam和单元测试2011-02-11 IBM Eric E. Allen在 Java 语言中获得单继承编程的安全性需要付出极大的代价:有时必须沿着继承层次结构中的多条路径复制代码。要重新获得单继承 Java 代码中所失去的大多数表示,我们可以将 mixin集成为一个扩展。本月,Eric Allen 解释了 mixin(那些由它们的父类参数化的类)的概念,以及它们如何能协助单元测试。他还描述了基于 mixin 编程的工具,并讨论了将 mixin 添加到您的 Java 代码中的可能方法。自从面向对象的编程出现以来,OO 语言设计中一直存在着一个困扰人的基本问题。一方面,我们在域分析过程中开发的本质是有意使用从多个父类继承的类。那是因为实际世界中的对象不会刚好适合一个简单的单继承层次结构。您最喜爱的啤酒或许口感既好纯度 又比较高。另一方面,在编程语言中允许多重继承的结果是语义极其复杂。在语言中引入这样的复杂性往往会使发生错误的概率增加,因此 Java 语言已经坚持采用单继承的方法(接口继承除外,其中的语义要简单得多)。其结果是,Java 程序中的许多类结构要么包含沿着继承层次结构的多个分支复制的代码,要么包含通过使用责任链(Chain of Responsibility)设计模式、命令(Command)设计模式或策略(Strategy)设计模式而添加的各个间接级别。例如,请考虑下面这个用于 GUI 库可滚动窗格的 UML 分析图示例:图 1. 选择 GUI 元素的分析图

理想情况下,我们希望将这个图直接转换成 Java 编程中的类层次结构。但是,因为 Java 编程是单继承,所以我们不能这么做。就算多重接口继承允许我们构造对应的接口集,但是实现这些接口的类不能直接遵循该结构。另一种方法是,我们要么必须沿着继承层次结构中的多条路径复制代码,要么使用策略模式(或其它使用限制的一些诀窍)来避免复制代码。这两种方法都不能完全让人满意。博采众长但是如果多重继承太容易出错,而单继承又太局限,那么在 Java 编程中是否可以添加一些语言特性,这些语言特性会向我们提供集中这两种方法的优点呢?答案是有的 ― 它就是 mixin。mixin 是那些由它们的父类参数化的类。它们也可以被认为是将类映射到新子类的函数。根据特定上下文的要求,可以用不同的父类实例化 mixin。例如,如下所示,通过使用 mixin 可以实现图 1 中 ScrollPane 的类层次结构(其中,存在定向的虚线代表从 mixin 到父类的实例化关系):图 2. mixin 继承图

在图 2 中,我们已经将类 Scrollable 转换成 mixin,它可以继承不同上下文中的不同类。在这个上下文中,我们实例化 Scrollable 以继承 Pane ,来创建 ScrollPane 。我们也可以实例化 Scrollable 以继承 Dialog ,而且我们可以对它实例化以继承不同上下文所需的所有种类的其它 GUI 组件。