Skip to content

Simplify Chinese translation of Scala Tour: lower-type-bounds.md #1199

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 14, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 56 additions & 1 deletion _zh-cn/tour/lower-type-bounds.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
layout: tour
title: Lower Type Bounds
title: 类型下界

discourse: false

Expand All @@ -13,3 +13,58 @@ language: zh-cn
next-page: inner-classes
previous-page: upper-type-bounds
---

[类型上界](upper-type-bounds.html) 将类型限制为另一种类型的子类型,而 *类型下界* 将类型声明为另一种类型的超类型。 术语 `B >: A` 表示类型参数 `B` 或抽象类型 `B` 是类型 `A` 的超类型。 在大多数情况下,`A` 将是类的类型参数,而 `B` 将是方法的类型参数。

下面看一个宜用类型下届的例子:

```tut:fail
trait Node[+B] {
def prepend(elem: B): Node[B]
}

case class ListNode[+B](h: B, t: Node[B]) extends Node[B] {
def prepend(elem: B): ListNode[B] = ListNode(elem, this)
def head: B = h
def tail: Node[B] = t
}

case class Nil[+B]() extends Node[B] {
def prepend(elem: B): ListNode[B] = ListNode(elem, this)
}
```

该程序实现了一个单链表。 `Nil` 表示空元素(即空列表)。 `class ListNode` 是一个节点,它包含一个类型为 `B` (`head`) 的元素和一个对列表其余部分的引用 (`tail`)。 `class Node` 及其子类型是协变的,因为我们定义了 `+B`。

但是,这个程序 _不能_ 编译,因为方法 `prepend` 中的参数 `elem` 是*协*变的 `B` 类型。 这会出错,因为函数的参数类型是*逆*变的,而返回类型是*协*变的。

要解决这个问题,我们需要将方法 `prepend` 的参数 `elem` 的型变翻转。 我们通过引入一个新的类型参数 `U` 来实现这一点,该参数具有 `B` 作为类型下界。

```tut
trait Node[+B] {
def prepend[U >: B](elem: U): Node[U]
}

case class ListNode[+B](h: B, t: Node[B]) extends Node[B] {
def prepend[U >: B](elem: U): ListNode[U] = ListNode(elem, this)
def head: B = h
def tail: Node[B] = t
}

case class Nil[+B]() extends Node[B] {
def prepend[U >: B](elem: U): ListNode[U] = ListNode(elem, this)
}
```

现在我们像下面这么做:
```tut
trait Bird
case class AfricanSwallow() extends Bird
case class EuropeanSwallow() extends Bird


val africanSwallowList= ListNode[AfricanSwallow](AfricanSwallow(), Nil())
val birdList: Node[Bird] = africanSwallowList
birdList.prepend(new EuropeanSwallow)
```
可以为 `Node[Bird]` 赋值 `africanSwallowList`,然后再加入一个 `EuropeanSwallow`。