Skip to content

Add Chinese translation of abstract-types and upper-type-bounds. #1181

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
Show file tree
Hide file tree
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
62 changes: 61 additions & 1 deletion _zh-cn/tour/abstract-types.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
layout: tour
title: Abstract Types
title: 抽象类型

discourse: false

Expand All @@ -13,3 +13,63 @@ language: zh-cn
next-page: compound-types
previous-page: inner-classes
---

特质和抽象类可以包含一个抽象类型成员,意味着实际类型可由具体实现来确定。例如:

```tut
trait Buffer {
type T
val element: T
}
```
这里定义的抽象类型`T`是用来描述成员`element`的类型的。通过抽象类来扩展这个特质后,就可以添加一个类型上边界来让抽象类型`T`变得更加具体。

```tut
abstract class SeqBuffer extends Buffer {
type U
type T <: Seq[U]
def length = element.length
}
```
注意这里是如何借助另外一个抽象类型`U`来限定类型上边界的。通过声明类型`T`只可以是`Seq[U]`的子类(其中U是一个新的抽象类型),这个`SeqBuffer`类就限定了缓冲区中存储的元素类型只能是序列。

含有抽象类型成员的特质或类([classes](classes.html))经常和匿名类的初始化一起使用。为了能够阐明问题,下面看一段程序,它处理一个涉及整型列表的序列缓冲区。

```tut
abstract class IntSeqBuffer extends SeqBuffer {
type U = Int
}


def newIntSeqBuf(elem1: Int, elem2: Int): IntSeqBuffer =
new IntSeqBuffer {
type T = List[U]
val element = List(elem1, elem2)
}
val buf = newIntSeqBuf(7, 8)
println("length = " + buf.length)
println("content = " + buf.element)
```
这里的工厂方法`newIntSeqBuf`使用了`IntSeqBuf`的匿名类实现方式,其类型`T`被设置成了`List[Int]`。

把抽象类型成员转成类的类型参数或者反过来,也是可行的。如下面这个版本只用了类的类型参数来转换上面的代码:

```tut
abstract class Buffer[+T] {
val element: T
}
abstract class SeqBuffer[U, +T <: Seq[U]] extends Buffer[T] {
def length = element.length
}

def newIntSeqBuf(e1: Int, e2: Int): SeqBuffer[Int, Seq[Int]] =
new SeqBuffer[Int, List[Int]] {
val element = List(e1, e2)
}

val buf = newIntSeqBuf(7, 8)
println("length = " + buf.length)
println("content = " + buf.element)
```

需要注意的是为了隐藏从方法`newIntSeqBuf`返回的对象的具体序列实现的类型,这里的[型变标号](variances.html)(`+T <: Seq[U]`)是必不可少的。此外要说明的是,有些情况下用类型参数替换抽象类型是行不通的。
41 changes: 40 additions & 1 deletion _zh-cn/tour/upper-type-bounds.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
layout: tour
title: Upper Type Bounds
title: 类型上界

discourse: false

Expand All @@ -13,3 +13,42 @@ language: zh-cn
next-page: lower-type-bounds
previous-page: variances
---

在Scala中,[类型参数](generic-classes.html)[抽象类型](abstract-types.html)都可以有一个类型边界约束。这种类型边界在限制类型变量实际取值的同时还能展露类型成员的更多信息。比如像`T <: A`这样声明的类型上界表示类型变量`T`应该是类型`A`的子类。下面的例子展示了类`PetContainer`的一个类型参数的类型上界。

```tut
abstract class Animal {
def name: String
}
abstract class Pet extends Animal {}
class Cat extends Pet {
override def name: String = "Cat"
}
class Dog extends Pet {
override def name: String = "Dog"
}
class Lion extends Animal {
override def name: String = "Lion"
}
class PetContainer[P <: Pet](p: P) {
def pet: P = p
}
val dogContainer = new PetContainer[Dog](new Dog)
val catContainer = new PetContainer[Cat](new Cat)
```

```tut:fail
// this would not compile
val lionContainer = new PetContainer[Lion](new Lion)
```
`PetContainer`接受一个必须是`Pet`子类的类型参数`P`。因为`Dog``Cat`都是`Pet`的子类,所以可以构造`PetContainer[Dog]``PetContainer[Cat]`。但在尝试构造`PetContainer[Lion]`的时候会得到下面的错误信息:

`type arguments [Lion] do not conform to class PetContainer's type parameter bounds [P <: Pet]`

这是因为`Lion`并不是`Pet`的子类。