# 9. 流继承

## 9.1.导言

流继承允许一个流继承另一个流的配置。继承可以在流和状态两个级别上发生。一个常见的用例是父流定义全局转换和异常处理程序，然后每个子流都可以继承这些设置。

为了找到父流，必须像其他任何流一样将其添加到`flow-registry`中。

## 9.2.流继承和 Java 继承一样吗？

流继承类似于 Java 继承，因为在父级中定义的元素是通过子级公开的，但是，有一些关键的区别。

子流不能覆盖父流中的元素。父流和子流之间的类似元素将被合并。父流中的唯一元素将被添加到子流中。

子流可以从多个父流继承。Java 继承仅限于一个类。

## 9.3.流继承的类型

### 9.3.1.流级继承

流级继承由`flow`元素上的`parent`属性定义。属性包含一个用逗号分隔的流标识符的列表。子流将按列出的顺序从每个父流继承，将元素和内容添加到结果流中。来自第一次合并的结果流将被认为是第二次合并中的子流，依此类推。

```
<flow parent="common-transitions, common-states">
			
```

### 9.3.2.状态级继承

状态级继承类似于流级继承，只是从父级继承了一个状态，而不是整个流。

与流继承不同，只允许有一个父代。此外，还必须定义要继承的流状态的标识符。流的标识符和该流中的状态由一个 # 分隔。

父状态和子状态必须是同一类型的。例如，一个视图状态不能从一个结束状态继承，只能从另一个视图状态继承。

```
<view-state id="child-state" parent="parent-flow#parent-view-state">
			
```

|[[note]（images/note.png）|Note|
|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:---|
|流级继承的意图是将公共状态定义为<br/>添加到多个流定义中并在多个流定义之间共享，而状态级继承的意图<br/>是从单个<br/>父状态扩展并合并。流级继承非常适合组合<br/>和多重继承，但是在状态级，你仍然只能从单个父状态继承<br/>。|    |

## 9.4.抽象流

通常，父流的设计不是为了直接执行。为了保护这些流不被运行，它们可以标记为`abstract`。如果一个抽象流试图运行，将抛出一个`FlowBuilderException`。

```
<flow abstract="true">
		
```

## 9.5.继承算法

当一个子流继承自它的父流时，本质上发生的情况是父流和子流合并在一起以创建一个新的流。对于 Web 流定义语言中的每个元素都有规则，这些规则控制该特定元素如何合并。

有两种类型的元素：*可合并*和*不可合并*。如果元素相似，可合并元素将始终尝试合并在一起。父流或子流中的不可合并元素将始终完整地包含在结果流中。它们不会作为合并过程的一部分进行修改。

|[[note]（images/note.png）|Note|
|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:---|
|到父流中的外部资源的路径应该是绝对的。<br/>当两个流合并时，相对路径将中断，除非父流和子流位于同一目录中。<br/>一旦合并，父流中的所有相对路径将变得相对于子流。|    |

### 9.5.1.可合并元素

如果元素的类型相同，且其键控属性相同，则父元素的内容将与子元素合并。合并算法将继续合并合并父元素和子元素的每个子元素。否则，父元素将作为一个新元素添加到子元素中。

在大多数情况下，添加的父流中的元素将在子流中的元素之后添加。此规则的例外包括将在开始时添加的动作元素（评估、渲染 和 集）。这允许子操作使用父操作的结果。

可合并的要素是：

* 动作状态：ID

* 属性：Name

* 决策状态：ID

* 结束状态：ID

* 流程：总是合并

* 如果：测试

* 端：总是合并

* 入门：总是合并

* On-Exit:总是合并

* On-Render:总是合并

* 启动：总是合并

* 输入：Name

* 输出：Name

* 安全：属性

* 子流-状态：id

* 转换：ON 和 ON-Exception

* 视图-状态：id

### 9.5.2.不可合并元素

不可合并的要素是：

* Bean-进口

* evaluate

* 异常处理程序

* 持久性-上下文

* render

* set

* VAR