From a80b035464148a6ff81b4d3a19dedf311c9863f7 Mon Sep 17 00:00:00 2001 From: Ben Luo Date: Mon, 20 Mar 2023 10:23:24 +0800 Subject: [PATCH 1/2] add code tab in five files. --- _overviews/scala3-book/types-generics.md | 5 +-- _overviews/scala3-book/types-intersection.md | 13 +++++++ .../overviews/scala3-book/types-generics.md | 35 +++++++++++++++++++ .../overviews/scala3-book/types-inferred.md | 12 +++++++ .../scala3-book/types-intersection.md | 17 ++++++++- 5 files changed, 79 insertions(+), 3 deletions(-) diff --git a/_overviews/scala3-book/types-generics.md b/_overviews/scala3-book/types-generics.md index c175158c55..25ace5eca4 100644 --- a/_overviews/scala3-book/types-generics.md +++ b/_overviews/scala3-book/types-generics.md @@ -63,7 +63,7 @@ This is how you create and use a `Stack[Int]`: {% tabs stack-usage class=tabs-scala-version %} {% tab 'Scala 2' %} -``` +```scala val stack = new Stack[Int] stack.push(1) stack.push(2) @@ -71,8 +71,9 @@ println(stack.pop()) // prints 2 println(stack.pop()) // prints 1 ``` {% endtab %} + {% tab 'Scala 3' %} -``` +```scala val stack = Stack[Int] stack.push(1) stack.push(2) diff --git a/_overviews/scala3-book/types-intersection.md b/_overviews/scala3-book/types-intersection.md index 9336b7dd68..8c01dd9b33 100644 --- a/_overviews/scala3-book/types-intersection.md +++ b/_overviews/scala3-book/types-intersection.md @@ -41,10 +41,23 @@ Therefore, as shown, `Resettable & Growable[String]` has member methods `reset` Intersection types can be useful to describe requirements _structurally_. That is, in our example `f`, we directly express that we are happy with any value for `x` as long as it’s a subtype of both `Resettable` and `Growable`. We **did not** have to create a _nominal_ helper trait like the following: + +{% tabs normal-trait class=tabs-scala-version %} +{% tab 'Scala 2' %} +```scala +trait Both[A] extends Resettable with Growable[A] +def f(x: Both[String]): Unit +``` +{% endtab %} + +{% tab 'Scala 3' %} ```scala trait Both[A] extends Resettable, Growable[A] def f(x: Both[String]): Unit ``` +{% endtab %} +{% endtabs %} + There is an important difference between the two alternatives of defining `f`: While both allow `f` to be called with instances of `Both`, only the former allows passing instances that are subtypes of `Resettable` and `Growable[String]`, but _not of_ `Both[String]`. > Note that `&` is _commutative_: `A & B` is the same type as `B & A`. diff --git a/_zh-cn/overviews/scala3-book/types-generics.md b/_zh-cn/overviews/scala3-book/types-generics.md index 45fb52865b..daa19bafba 100644 --- a/_zh-cn/overviews/scala3-book/types-generics.md +++ b/_zh-cn/overviews/scala3-book/types-generics.md @@ -18,6 +18,29 @@ permalink: "/zh-cn/scala3/book/:title.html" Scala 约定是使用单个字母(如 `A`)来命名这些类型参数。 然后当需要时,该类型可以在类中用于方法实例参数,或返回类型: +{% tabs stack class=tabs-scala-version %} +{% tab 'Scala 2' %} +```scala +// here we declare the type parameter A +// v +class Stack[A] { + private var elements: List[A] = Nil + // ^ + // Here we refer to the type parameter + // v + def push(x: A): Unit = + elements = elements.prepended(x) + def peek: A = elements.head + def pop(): A = { + val currentTop = peek + elements = elements.tail + currentTop + } +} +``` +{% endtab %} + +{% tab 'Scala 3' %} ```scala // here we declare the type parameter A // v @@ -39,7 +62,19 @@ class Stack[A]: 这是创建和使用 `Stack[Int]` 的方式: +{% tabs stack-usage class=tabs-scala-version %} +{% tab 'Scala 2' %} +```scala +val stack = new Stack[Int] +stack.push(1) +stack.push(2) +println(stack.pop()) // prints 2 +println(stack.pop()) // prints 1 ``` +{% endtab %} + +{% tab 'Scala 3' %} +```scala val stack = Stack[Int] stack.push(1) stack.push(2) diff --git a/_zh-cn/overviews/scala3-book/types-inferred.md b/_zh-cn/overviews/scala3-book/types-inferred.md index ba52c8a9ce..b524a03edd 100644 --- a/_zh-cn/overviews/scala3-book/types-inferred.md +++ b/_zh-cn/overviews/scala3-book/types-inferred.md @@ -16,22 +16,32 @@ permalink: "/zh-cn/scala3/book/:title.html" 与其他静态类型编程语言一样,在 Scala 中,您可以在创建新变量时_声明_类型: +{% tabs xy %} +{% tab 'Scala 2 and 3' %} ```scala val x: Int = 1 val y: Double = 1 ``` +{% endtab %} +{% endtabs %} 在这些示例中,类型分别_明确地_声明为 `Int` 和 `Double` 。 但是,在 Scala 中,您通常不必在定义值绑定器时声明类型: +{% tabs abm %} +{% tab 'Scala 2 and 3' %} ```scala val a = 1 val b = List(1, 2, 3) val m = Map(1 -> "one", 2 -> "two") ``` +{% endtab %} +{% endtabs %} 当你这样做时,Scala _推断_类型,如下面的 REPL 交互所示: +{% tabs abm2 %} +{% tab 'Scala 2 and 3' %} ```scala scala> val a = 1 val a: Int = 1 @@ -42,5 +52,7 @@ val b: List[Int] = List(1, 2, 3) scala> val m = Map(1 -> "one", 2 -> "two") val m: Map[Int, String] = Map(1 -> one, 2 -> two) ``` +{% endtab %} +{% endtabs %} 事实上,大多数变量都是这样定义的,而 Scala 自动推断类型的能力是使它_感觉_像一种动态类型语言的一个特性。 diff --git a/_zh-cn/overviews/scala3-book/types-intersection.md b/_zh-cn/overviews/scala3-book/types-intersection.md index 085c92c893..c61548e163 100644 --- a/_zh-cn/overviews/scala3-book/types-intersection.md +++ b/_zh-cn/overviews/scala3-book/types-intersection.md @@ -12,12 +12,14 @@ overview-name: "Scala 3 — Book" layout: multipage-overview permalink: "/zh-cn/scala3/book/:title.html" --- - +Scala 3 only 用于类型,`&` 运算符创建一个所谓的_相交类型_。 `A & B` 类型表示同时是 `A` 类型和 `B` 类型**两者**的值。 例如,以下示例使用相交类型 `Resettable & Growable[String]`: +{% tabs intersection-reset-grow %} +{% tab 'Scala 3 Only' %} ```scala trait Resettable: def reset(): Unit @@ -29,6 +31,8 @@ def f(x: Resettable & Growable[String]): Unit = x.reset() x.add("first") ``` +{% endtab %} +{% endtabs %} 在本例中的方法 `f` 中,参数 `x` 必须*同时*既是 `Resettable` 也是 `Growable[String]`。 @@ -39,10 +43,21 @@ def f(x: Resettable & Growable[String]): Unit = 也就是说,在我们的示例 `f` 中,我们直接表示只要 `x` 是 `Resettable` 和 `Growable` 的子类型的任意值, 我们就感到满意。 我们**不**需要创建一个_通用_的辅助 trait,如下所示: +{% tabs normal-trait class=tabs-scala-version %} +{% tab 'Scala 2' %} +```scala +trait Both[A] extends Resettable with Growable[A] +def f(x: Both[String]): Unit +``` +{% endtab %} + +{% tab 'Scala 3' %} ```scala trait Both[A] extends Resettable, Growable[A] def f(x: Both[String]): Unit ``` +{% endtab %} +{% endtabs %} 定义 `f` 的两种选择之间有一个重要区别:虽然两者都允许使用 `Both` 的实例调用 `f`,但只有前者允许传递属于 `Resettable` 和 `Growable[String]` 子类型的实例,后者 `Both[String]` _不允许_。 From 0ceed97c08f817d853d122e1eecd78950073448a Mon Sep 17 00:00:00 2001 From: Ben Luo Date: Mon, 20 Mar 2023 12:38:02 +0800 Subject: [PATCH 2/2] corrected in types-generics.md. --- _zh-cn/overviews/scala3-book/types-generics.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/_zh-cn/overviews/scala3-book/types-generics.md b/_zh-cn/overviews/scala3-book/types-generics.md index daa19bafba..8e036c4b77 100644 --- a/_zh-cn/overviews/scala3-book/types-generics.md +++ b/_zh-cn/overviews/scala3-book/types-generics.md @@ -56,6 +56,8 @@ class Stack[A]: elements = elements.tail currentTop ``` +{% endtab %} +{% endtabs %} `Stack` 类的这个实现采用任何类型作为参数。 泛型的美妙之处在于您现在可以创建一个 `Stack[Int]`、`Stack[String]` 等,允许您将 `Stack` 的实现重复用于任意元素类型。 @@ -81,6 +83,8 @@ stack.push(2) println(stack.pop()) // prints 2 println(stack.pop()) // prints 1 ``` +{% endtab %} +{% endtabs %} > 有关如何用泛型类型表达可变的详细信息,请参阅[型变(Variance)部分][variance]。