23, generics, for 3.1 (#691)
* 翻译<泛型>中3.1添加的部分 * 去掉在上文添加的两个空格 * 英文添加加空格或单引号 * 在`xxx`前后添加空格
This commit is contained in:
@ -17,6 +17,8 @@
|
|||||||
> 3.0:翻译+校对:[chenmingjia](https://github.com/chenmingjia),2016-09-12
|
> 3.0:翻译+校对:[chenmingjia](https://github.com/chenmingjia),2016-09-12
|
||||||
> 3.0.1,shanks,2016-11-13
|
> 3.0.1,shanks,2016-11-13
|
||||||
|
|
||||||
|
> 3.1:翻译:[qhd](https://github.com/qhd),2017-04-10
|
||||||
|
|
||||||
本页包含内容:
|
本页包含内容:
|
||||||
|
|
||||||
- [泛型所解决的问题](#the_problem_that_generics_solve)
|
- [泛型所解决的问题](#the_problem_that_generics_solve)
|
||||||
@ -28,6 +30,7 @@
|
|||||||
- [类型约束](#type_constraints)
|
- [类型约束](#type_constraints)
|
||||||
- [关联类型](#associated_types)
|
- [关联类型](#associated_types)
|
||||||
- [泛型 Where 语句](#where_clauses)
|
- [泛型 Where 语句](#where_clauses)
|
||||||
|
- [具有泛型 where 子句的扩展](#extensions_with_a_generic_where_clause)
|
||||||
|
|
||||||
*泛型代码*让你能够根据自定义的需求,编写出适用于任意类型、灵活可重用的函数及类型。它能让你避免代码的重复,用一种清晰和抽象的方式来表达代码的意图。
|
*泛型代码*让你能够根据自定义的需求,编写出适用于任意类型、灵活可重用的函数及类型。它能让你避免代码的重复,用一种清晰和抽象的方式来表达代码的意图。
|
||||||
|
|
||||||
@ -536,3 +539,83 @@ if allItemsMatch(stackOfStrings, arrayOfStrings) {
|
|||||||
```
|
```
|
||||||
|
|
||||||
上面的例子创建了一个 `Stack` 实例来存储一些 `String` 值,然后将三个字符串压入栈中。这个例子还通过数组字面量创建了一个 `Array` 实例,数组中包含同栈中一样的三个字符串。即使栈和数组是不同的类型,但它们都遵从 `Container` 协议,而且它们都包含相同类型的值。因此你可以用这两个容器作为参数来调用 `allItemsMatch(_:_:)` 函数。在上面的例子中,`allItemsMatch(_:_:)` 函数正确地显示了这两个容器中的所有元素都是相互匹配的。
|
上面的例子创建了一个 `Stack` 实例来存储一些 `String` 值,然后将三个字符串压入栈中。这个例子还通过数组字面量创建了一个 `Array` 实例,数组中包含同栈中一样的三个字符串。即使栈和数组是不同的类型,但它们都遵从 `Container` 协议,而且它们都包含相同类型的值。因此你可以用这两个容器作为参数来调用 `allItemsMatch(_:_:)` 函数。在上面的例子中,`allItemsMatch(_:_:)` 函数正确地显示了这两个容器中的所有元素都是相互匹配的。
|
||||||
|
|
||||||
|
<a name="extensions_with_a_generic_where_clause"></a>
|
||||||
|
## 具有泛型 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<NotEquatable>()
|
||||||
|
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..<count {
|
||||||
|
sum += self[index]
|
||||||
|
}
|
||||||
|
return sum / Double(count)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print([1260.0, 1200.0, 98.6, 37.0].average())
|
||||||
|
// 打印 "648.9"
|
||||||
|
```
|
||||||
|
|
||||||
|
此示例将一个 `average()` 方法添加到 `Item` 类型为 `Double` 的容器中。此方法遍历容器中的元素将其累加,并除以容器的数量计算平均值。它将数量从 `Int` 转换为 `Double` 确保能够进行浮点除法。
|
||||||
|
|
||||||
|
就像可以在其他地方写泛型 `where` 子句一样,你可以在一个泛型 `where` 子句中包含多个条件作为扩展的一部分。用逗号分隔列表中的每个条件。
|
||||||
|
|||||||
Reference in New Issue
Block a user