diff --git a/_zh-cn/overviews/scala3-book/taste-functions.md b/_zh-cn/overviews/scala3-book/taste-functions.md index 9c52d09213..ca6725f77d 100644 --- a/_zh-cn/overviews/scala3-book/taste-functions.md +++ b/_zh-cn/overviews/scala3-book/taste-functions.md @@ -26,13 +26,23 @@ Lambdas(也称为 _匿名函数_)是保持代码简洁但可读性的重要 这两个示例是等效的,并演示如何通过将 lambda 传递到 `map` 方法中,将列表中的每个数字乘以 `2`: + +{% tabs function_1 %} +{% tab 'Scala 2 and 3' for=function_1 %} + ```scala val a = List(1, 2, 3).map(i => i * 2) // List(2,4,6) val b = List(1, 2, 3).map(_ * 2) // List(2,4,6) ``` +{% endtab %} +{% endtabs %} + 这些示例也等效于以下代码,该代码使用 `double` 方法而不是lambda: +{% tabs function_2 %} +{% tab 'Scala 2 and 3' for=function_2 %} + ```scala def double(i: Int): Int = i * 2 @@ -40,6 +50,9 @@ val a = List(1, 2, 3).map(i => double(i)) // List(2,4,6) val b = List(1, 2, 3).map(double) // List(2,4,6) ``` +{% endtab %} +{% endtabs %} + > 如果您以前从未见过 `map` 方法,它会将给定的函数应用于列表中的每个元素,从而生成一个包含结果值的新列表。 将 lambda 传递给集合类上的高阶函数(如 `List`)是 Scala 体验的一部分,您每天都会这样做。 @@ -51,6 +64,9 @@ val b = List(1, 2, 3).map(double) // List(2,4,6) 例如,此示例演示如何对一个集合进行两次筛选,然后将其余集合中的每个元素乘某个数: +{% tabs function_3 %} +{% tab 'Scala 2 and 3' for=function_3 %} + ```scala // a sample list val nums = (1 to 10).toList // List(1,2,3,4,5,6,7,8,9,10) @@ -63,6 +79,9 @@ val x = nums.filter(_ > 3) // result: x == List(40, 50, 60) ``` +{% endtab %} +{% endtabs %} + 除了在整个标准库中使用的高阶函数外,您还可以[创建自己的][higher-order] 高阶函数。 [higher-order]: {% link _zh-cn/overviews/scala3-book/fun-hofs.md %} diff --git a/_zh-cn/overviews/scala3-book/taste-methods.md b/_zh-cn/overviews/scala3-book/taste-methods.md index 10e57ece93..25b6017ba6 100644 --- a/_zh-cn/overviews/scala3-book/taste-methods.md +++ b/_zh-cn/overviews/scala3-book/taste-methods.md @@ -19,35 +19,73 @@ permalink: "/zh-cn/scala3/book/:title.html" Scala 类、样例类、traits、枚举和对象都可以包含方法。 简单方法的语法如下所示: +{% tabs method_1 %} +{% tab 'Scala 2 and 3' for=method_1 %} + ```scala def methodName(param1: Type1, param2: Type2): ReturnType = // the method body // goes here ``` +{% endtab %} +{% endtabs %} + 这有一些例子: +{% tabs method_2 %} +{% tab 'Scala 2 and 3' for=method_2 %} + ```scala def sum(a: Int, b: Int): Int = a + b def concatenate(s1: String, s2: String): String = s1 + s2 ``` +{% endtab %} +{% endtabs %} + 您不必声明方法的返回类型,因此如果您愿意,可以像这样编写这些方法: +{% tabs method_3 %} +{% tab 'Scala 2 and 3' for=method_3 %} + ```scala def sum(a: Int, b: Int) = a + b def concatenate(s1: String, s2: String) = s1 + s2 ``` +{% endtab %} +{% endtabs %} + 这是你如何调用这些方法: +{% tabs method_4 %} +{% tab 'Scala 2 and 3' for=method_4 %} + ```scala val x = sum(1, 2) val y = concatenate("foo", "bar") ``` +{% endtab %} +{% endtabs %} + 这是一个多行的方法: +{% tabs method_5 class=tabs-scala-version %} +{% tab 'Scala 2' for=method_5 %} + +```scala +def getStackTraceAsString(t: Throwable): String = { + val sw = new StringWriter + t.printStackTrace(new PrintWriter(sw)) + sw.toString +} +``` + +{% endtab %} +{% tab 'Scala 3' for=method_5 %} + ```scala def getStackTraceAsString(t: Throwable): String = val sw = new StringWriter @@ -55,23 +93,41 @@ def getStackTraceAsString(t: Throwable): String = sw.toString ``` +{% endtab %} +{% endtabs %} + 方法参数也可以具有默认值。 在此示例中,`timeout` 参数的默认值为 `5000`: +{% tabs method_6 %} +{% tab 'Scala 2 and 3' for=method_6 %} + ```scala def makeConnection(url: String, timeout: Int = 5000): Unit = println(s"url=$url, timeout=$timeout") ``` +{% endtab %} +{% endtabs %} + 由于方法声明中提供了默认的 `超时` 值,因此可以通过以下两种方式调用该方法: +{% tabs method_7 %} +{% tab 'Scala 2 and 3' for=method_7 %} + ```scala makeConnection("https://localhost") // url=http://localhost, timeout=5000 makeConnection("https://localhost", 2500) // url=http://localhost, timeout=2500 ``` +{% endtab %} +{% endtabs %} + Scala 还支持在调用方法时使用 _命名参数_,因此如果您愿意,也可以像这样调用该方法: +{% tabs method_8 %} +{% tab 'Scala 2 and 3' for=method_8 %} + ```scala makeConnection( url = "https://localhost", @@ -79,15 +135,27 @@ makeConnection( ) ``` +{% endtab %} +{% endtabs %} + 当多个方法参数具有相同的类型时,命名参数特别有用。 乍一看,使用此方法,您可能想知道哪些参数设置为 `true` 或 `false`: +{% tabs method_9 %} +{% tab 'Scala 2 and 3' for=method_9 %} + ```scala engage(true, true, true, false) ``` +{% endtab %} +{% endtabs %} + 如果没有IDE的帮助,那段代码可能很难阅读,但这个代码要明显得多: +{% tabs method_10 %} +{% tab 'Scala 2 and 3' for=method_10 %} + ```scala engage( speedIsSet = true, @@ -96,12 +164,17 @@ engage( turnedOffParkingBrake = false ) ``` +{% endtab %} +{% endtabs %} ## 扩展方法 _扩展方法_ 允许您向封闭类添加新方法。 例如,如果要将两个名为 `hello` 和 `aloha` 的方法添加到 `String` 类中,请将它们声明为扩展方法: +{% tabs extension0 %} +{% tab 'Scala 3 Only' %} + ```scala extension (s: String) def hello: String = s"Hello, ${s.capitalize}!" @@ -111,6 +184,9 @@ extension (s: String) "friend".aloha // "Aloha, Friend!" ``` +{% endtab %} +{% endtabs %} + `extension` 关键字声明了括号内的参数将定义一个或多个扩展方法。 如此示例所示,可以在扩展方法体中使用 `String` 类型的参数 `s`。 @@ -118,6 +194,9 @@ extension (s: String) 在这里,`makeInt` 采用一个名为 `radix` 的参数。 该代码不考虑可能的字符串到整数转换错误,但跳过细节,示例显示了它的工作原理: +{% tabs extension %} +{% tab 'Scala 3 Only' %} + ```scala extension (s: String) def makeInt(radix: Int): Int = Integer.parseInt(s, radix) @@ -127,7 +206,10 @@ extension (s: String) "100".makeInt(2) // Int = 4 ``` -## See also +{% endtab %} +{% endtabs %} + +## 参见 Scala方法可以更强大:它们可以采用类型参数和上下文参数。 它们在[领域建模][data-1]一节中有详细介绍。