diff --git a/source/chapter2/23_Generics.md b/source/chapter2/23_Generics.md
index f45c5a49..da678988 100644
--- a/source/chapter2/23_Generics.md
+++ b/source/chapter2/23_Generics.md
@@ -17,6 +17,8 @@
> 3.0:翻译+校对:[chenmingjia](https://github.com/chenmingjia),2016-09-12
> 3.0.1,shanks,2016-11-13
+> 3.1:翻译:[qhd](https://github.com/qhd),2017-04-10
+
本页包含内容:
- [泛型所解决的问题](#the_problem_that_generics_solve)
@@ -28,6 +30,7 @@
- [类型约束](#type_constraints)
- [关联类型](#associated_types)
- [泛型 Where 语句](#where_clauses)
+- [具有泛型 where 子句的扩展](#extensions_with_a_generic_where_clause)
*泛型代码*让你能够根据自定义的需求,编写出适用于任意类型、灵活可重用的函数及类型。它能让你避免代码的重复,用一种清晰和抽象的方式来表达代码的意图。
@@ -536,3 +539,83 @@ if allItemsMatch(stackOfStrings, arrayOfStrings) {
```
上面的例子创建了一个 `Stack` 实例来存储一些 `String` 值,然后将三个字符串压入栈中。这个例子还通过数组字面量创建了一个 `Array` 实例,数组中包含同栈中一样的三个字符串。即使栈和数组是不同的类型,但它们都遵从 `Container` 协议,而且它们都包含相同类型的值。因此你可以用这两个容器作为参数来调用 `allItemsMatch(_:_:)` 函数。在上面的例子中,`allItemsMatch(_:_:)` 函数正确地显示了这两个容器中的所有元素都是相互匹配的。
+
+
+## 具有泛型 where 子句的扩展
+
+你也可以使用泛型 `where` 子句作为扩展的一部分。基于以前的例子,下面的示例扩展了泛型 `Stack` 结构体,添加一个 `isTop(_:)` 方法。
+
+```swift
+extension Stack where Element: Equatable {
+ func isTop(_ item: Element) -> Bool {
+ guard let topItem = items.last else {
+ return false
+ }
+ return topItem == item
+ }
+}
+```
+
+这个新的 `isTop(_:)` 方法首先检查这个栈是不是空的,然后比较给定的元素与栈顶部的元素。如果你尝试不用泛型 `where` 子句,会有一个问题:在 `isTop(_:)` 里面使用了 `==` 运算符,但是 `Stack` 的定义没有要求它的元素是符合 Equatable 协议的,所以使用 `==` 运算符导致编译时错误。使用泛型 `where` 子句可以为扩展添加新的条件,因此只有当栈中的元素符合 Equatable 协议时,扩展才会添加 `isTop(_:)` 方法。
+
+以下是 `isTop(_:)` 方法的调用方式:
+
+```swift
+if stackOfStrings.isTop("tres") {
+ print("Top element is tres.")
+} else {
+ print("Top element is something else.")
+}
+// 打印 "Top element is tres."
+```
+
+如果尝试在其元素不符合 Equatable 协议的栈上调用 `isTop(_:)` 方法,则会收到编译时错误。
+
+```swift
+struct NotEquatable { }
+var notEquatableStack = Stack()
+let notEquatableValue = NotEquatable()
+notEquatableStack.push(notEquatableValue)
+notEquatableStack.isTop(notEquatableValue) // 报错
+```
+
+你可以使用泛型 `where` 子句去扩展一个协议。基于以前的示例,下面的示例扩展了 `Container` 协议,添加一个 `startsWith(_:)` 方法。
+
+```swift
+extension Container where Item: Equatable {
+ func startsWith(_ item: Item) -> Bool {
+ return count >= 1 && self[0] == item
+ }
+}
+```
+
+这个 `startsWith(_:)` 方法首先确保容器至少有一个元素,然后检查容器中的第一个元素是否与给定的元素相等。任何符合 `Container` 协议的类型都可以使用这个新的 `startsWith(_:)` 方法,包括上面使用的栈和数组,只要容器的元素是符合 Equatable 协议的。
+
+```swift
+if [9, 9, 9].startsWith(42) {
+ print("Starts with 42.")
+} else {
+ print("Starts with something else.")
+}
+// 打印 "Starts with something else."
+```
+
+上述示例中的泛型 `where` 子句要求 `Item` 符合协议,但也可以编写一个泛型 `where` 子句去要求 `Item` 为特定类型。例如:
+
+```swift
+extension Container where Item == Double {
+ func average() -> Double {
+ var sum = 0.0
+ for index in 0..