From d476fef4e91d93c916b2388821585aae8a1212b0 Mon Sep 17 00:00:00 2001 From: cunchen Date: Thu, 11 Oct 2018 21:35:10 +0800 Subject: [PATCH 1/3] Update abstract-types.md --- _zh-cn/tour/abstract-types.md | 65 ++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/_zh-cn/tour/abstract-types.md b/_zh-cn/tour/abstract-types.md index 6fe6dcdf04..50e8348870 100644 --- a/_zh-cn/tour/abstract-types.md +++ b/_zh-cn/tour/abstract-types.md @@ -1,6 +1,6 @@ --- layout: tour -title: Abstract Types +title: 抽象类型 discourse: false @@ -13,3 +13,66 @@ language: zh-cn next-page: compound-types previous-page: inner-classes --- +特征(Trait)和抽象类(abstract class)可以包含抽象类型成员。这表示具体的实现可以在具体类型中。示例如下: +```$scala +trait Buffer { + type T + val element: T +} +``` +这里我们定义了一个抽象类型 `tpye T`,用于修饰`element`的类型。 +如示例,我们可以用抽象类继承特征,并增加类型边界上限把`T`描述的更加具体。 +```$scala +abstract class SeqBuffer extends Buffer { + type U + type T <: Seq[U] + def length = element.length +} +``` +需要注意的是我们之前没有使用过抽象类型`type U`做类型边界上限。 +这个`Class SeqBuffer`只允许我们在Buffer中存入序列类型是`Seq[U]`子类的`T`,并且U是一个新的抽象类型。 + +特征和抽象类经常和匿名类一起使用。示例如下,我们现在看一个程序,它处理一个引用整数列表的序列Buffer: + +```$scala +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的匿名类实例(i.e. `new IntSeqBuffer`), +并设置抽象类型`type T`为`List[Int]` + + + +也可以将抽象类型成员转换为类的类型参数,反之亦然。这是上面代码的一个版本,它只使用类型参数: +```$scala +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) +``` + +注意这里我们使用了[变异标记(Variance Annotations)](https://docs.scala-lang.org/zh-cn/tour/variances.html)(`+T <: Seq[U]`)隐藏方法`newIntSeqBuf`返回对象的具体序列的实现类型。 +此外,有些情况下无法用类型参数替换抽象类型。 From 01cb8e05fce29904083eefdb9ae7d98b5c132225 Mon Sep 17 00:00:00 2001 From: cunchen Date: Fri, 12 Oct 2018 14:00:01 +0800 Subject: [PATCH 2/3] Update abstract-types.md --- _zh-cn/tour/abstract-types.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_zh-cn/tour/abstract-types.md b/_zh-cn/tour/abstract-types.md index 50e8348870..5b3087d0ed 100644 --- a/_zh-cn/tour/abstract-types.md +++ b/_zh-cn/tour/abstract-types.md @@ -13,7 +13,7 @@ language: zh-cn next-page: compound-types previous-page: inner-classes --- -特征(Trait)和抽象类(abstract class)可以包含抽象类型成员。这表示具体的实现可以在具体类型中。示例如下: +特征(Trait)和抽象类(abstract class)可以包含一个抽象类型成员,意味着实际类型可由具体实现来确定。示例如下: ```$scala trait Buffer { type T From 986ec91100912bbf6ef82843a055f9d9bfe4807e Mon Sep 17 00:00:00 2001 From: cunchen Date: Tue, 16 Oct 2018 18:57:37 +0800 Subject: [PATCH 3/3] Update abstract-types.md --- _zh-cn/tour/abstract-types.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/_zh-cn/tour/abstract-types.md b/_zh-cn/tour/abstract-types.md index 5b3087d0ed..0a20df62df 100644 --- a/_zh-cn/tour/abstract-types.md +++ b/_zh-cn/tour/abstract-types.md @@ -29,8 +29,7 @@ abstract class SeqBuffer extends Buffer { def length = element.length } ``` -需要注意的是我们之前没有使用过抽象类型`type U`做类型边界上限。 -这个`Class SeqBuffer`只允许我们在Buffer中存入序列类型是`Seq[U]`子类的`T`,并且U是一个新的抽象类型。 +注意这里是如何借助另外一个抽象类型U来限定类型边界上限(upper-type-bound)。通过声明类型T只可以是Seq[U]的子类(其中U是一个新的抽象类型),这个SeqBuffer类就限定了缓冲区中存储的元素类型只能是序列。 特征和抽象类经常和匿名类一起使用。示例如下,我们现在看一个程序,它处理一个引用整数列表的序列Buffer: