Skip to content

Commit cbe7216

Browse files
authored
Merge pull request scala#1181 from dongxuwang/master
Add Chinese translation of abstract-types and upper-type-bounds.
2 parents 48db28f + 7a48e66 commit cbe7216

File tree

2 files changed

+101
-2
lines changed

2 files changed

+101
-2
lines changed

_zh-cn/tour/abstract-types.md

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
layout: tour
3-
title: Abstract Types
3+
title: 抽象类型
44

55
discourse: false
66

@@ -13,3 +13,63 @@ language: zh-cn
1313
next-page: compound-types
1414
previous-page: inner-classes
1515
---
16+
17+
特质和抽象类可以包含一个抽象类型成员,意味着实际类型可由具体实现来确定。例如:
18+
19+
```tut
20+
trait Buffer {
21+
type T
22+
val element: T
23+
}
24+
```
25+
这里定义的抽象类型`T`是用来描述成员`element`的类型的。通过抽象类来扩展这个特质后,就可以添加一个类型上边界来让抽象类型`T`变得更加具体。
26+
27+
```tut
28+
abstract class SeqBuffer extends Buffer {
29+
type U
30+
type T <: Seq[U]
31+
def length = element.length
32+
}
33+
```
34+
注意这里是如何借助另外一个抽象类型`U`来限定类型上边界的。通过声明类型`T`只可以是`Seq[U]`的子类(其中U是一个新的抽象类型),这个`SeqBuffer`类就限定了缓冲区中存储的元素类型只能是序列。
35+
36+
含有抽象类型成员的特质或类([classes](classes.html))经常和匿名类的初始化一起使用。为了能够阐明问题,下面看一段程序,它处理一个涉及整型列表的序列缓冲区。
37+
38+
```tut
39+
abstract class IntSeqBuffer extends SeqBuffer {
40+
type U = Int
41+
}
42+
43+
44+
def newIntSeqBuf(elem1: Int, elem2: Int): IntSeqBuffer =
45+
new IntSeqBuffer {
46+
type T = List[U]
47+
val element = List(elem1, elem2)
48+
}
49+
val buf = newIntSeqBuf(7, 8)
50+
println("length = " + buf.length)
51+
println("content = " + buf.element)
52+
```
53+
这里的工厂方法`newIntSeqBuf`使用了`IntSeqBuf`的匿名类实现方式,其类型`T`被设置成了`List[Int]`
54+
55+
把抽象类型成员转成类的类型参数或者反过来,也是可行的。如下面这个版本只用了类的类型参数来转换上面的代码:
56+
57+
```tut
58+
abstract class Buffer[+T] {
59+
val element: T
60+
}
61+
abstract class SeqBuffer[U, +T <: Seq[U]] extends Buffer[T] {
62+
def length = element.length
63+
}
64+
65+
def newIntSeqBuf(e1: Int, e2: Int): SeqBuffer[Int, Seq[Int]] =
66+
new SeqBuffer[Int, List[Int]] {
67+
val element = List(e1, e2)
68+
}
69+
70+
val buf = newIntSeqBuf(7, 8)
71+
println("length = " + buf.length)
72+
println("content = " + buf.element)
73+
```
74+
75+
需要注意的是为了隐藏从方法`newIntSeqBuf`返回的对象的具体序列实现的类型,这里的[型变标号](variances.html)`+T <: Seq[U]`)是必不可少的。此外要说明的是,有些情况下用类型参数替换抽象类型是行不通的。

_zh-cn/tour/upper-type-bounds.md

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
layout: tour
3-
title: Upper Type Bounds
3+
title: 类型上界
44

55
discourse: false
66

@@ -13,3 +13,42 @@ language: zh-cn
1313
next-page: lower-type-bounds
1414
previous-page: variances
1515
---
16+
17+
在Scala中,[类型参数](generic-classes.html)[抽象类型](abstract-types.html)都可以有一个类型边界约束。这种类型边界在限制类型变量实际取值的同时还能展露类型成员的更多信息。比如像`T <: A`这样声明的类型上界表示类型变量`T`应该是类型`A`的子类。下面的例子展示了类`PetContainer`的一个类型参数的类型上界。
18+
19+
```tut
20+
abstract class Animal {
21+
def name: String
22+
}
23+
24+
abstract class Pet extends Animal {}
25+
26+
class Cat extends Pet {
27+
override def name: String = "Cat"
28+
}
29+
30+
class Dog extends Pet {
31+
override def name: String = "Dog"
32+
}
33+
34+
class Lion extends Animal {
35+
override def name: String = "Lion"
36+
}
37+
38+
class PetContainer[P <: Pet](p: P) {
39+
def pet: P = p
40+
}
41+
42+
val dogContainer = new PetContainer[Dog](new Dog)
43+
val catContainer = new PetContainer[Cat](new Cat)
44+
```
45+
46+
```tut:fail
47+
// this would not compile
48+
val lionContainer = new PetContainer[Lion](new Lion)
49+
```
50+
`PetContainer`接受一个必须是`Pet`子类的类型参数`P`。因为`Dog``Cat`都是`Pet`的子类,所以可以构造`PetContainer[Dog]``PetContainer[Cat]`。但在尝试构造`PetContainer[Lion]`的时候会得到下面的错误信息:
51+
52+
`type arguments [Lion] do not conform to class PetContainer's type parameter bounds [P <: Pet]`
53+
54+
这是因为`Lion`并不是`Pet`的子类。

0 commit comments

Comments
 (0)