Scala学习之Scala快速入门
Posted 顧棟
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Scala学习之Scala快速入门相关的知识,希望对你有一定的参考价值。
文章目录
Scala的“味道”
原文地址: https://docs.scala-lang.org/overviews/scala-book/prelude-taste-of-scala.html
在本书中,我们假设您以前使用过 Java 之类的语言,并准备好查看一系列 Scala 示例以了解该语言的外观。 尽管这不是 100% 必要的,但如果您已经下载并安装了 Scala,它也会有所帮助,这样您就可以在进行过程中测试示例。 您还可以使用 ScalaFiddle.io 在线测试这些示例。
Overview 概述
在我们进入示例之前,这里有一些关于 Scala 的重要信息:
- 这是一种高级语言
- 它是静态类型的
- 它的语法简洁但仍然可读——我们称之为富有表现力
- 它支持面向对象编程 (OOP) 范式
- 它支持函数式编程 (FP) 范式
- 它有一个复杂的类型推断系统
- Scala 代码生成在 Java 虚拟机 (JVM) 上运行的 .class 文件
- 在 Scala 中使用 Java 库很容易
Hello, world
从《C 编程语言》这本书开始,以“Hello, world”示例开始编程书籍一直是一种传统,不要让人失望,这是在 Scala 中编写该示例的一种方式:
object Hello extends App {
println("Hello, world")
}
将该代码保存到名为 Hello.scala 的文件后,您可以使用scalac
编译它:
$ scalac Hello.scala
如果您是从 Java 来到 Scala,scalac 就像 javac,该命令会创建两个文件:
- Hello$.class
- Hello.class
这些与您使用 javac 创建的“.class”字节码文件相同,它们已准备好在 JVM 中运行。 使用 scala 命令运行 Hello 应用程序:
$ scala Hello
我们将在接下来的课程中分享更多“Hello, world”示例,因此我们暂时保留该介绍。
The Scala REPL
Scala REPL(“Read-Evaluate-Print-Loop”)是一个命令行解释器,您可以将其用作测试 Scala 代码的“操场”区域。 我们在这里很早就介绍了它,以便您可以将它与后面的代码示例一起使用。
要启动 REPL 会话,只需在您的操作系统命令行中输入 scala,您将看到如下内容:
$ scala
Welcome to Scala 2.13.0 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_131).
Type in expressions for evaluation. Or try :help.
scala> _
因为 REPL 是一个命令行解释器,它只是坐在那里等待你输入一些东西。 在 REPL 中,您键入 Scala 表达式以查看它们是如何工作的:
scala> val x = 1
x: Int = 1
scala> val y = x + 1
y: Int = 2
如这些示例所示,在 REPL 中键入表达式后,它会在提示后的行中显示每个表达式的结果。
Two types of variables
Scala 有两种类型的变量:
val
is an immutable variable — likefinal
in Java — and should be preferredvar
creates a mutable variable, and should only be used when there is a specific reason to use it- Examples:
val x = 1 //immutable
var y = 0 //mutable
Declaring variable types
在 Scala 中,您通常创建变量而不声明它们的类型:
val x = 1
val s = "a string"
val p = new Person("Regina")
当您这样做时,Scala 通常可以为您推断数据类型,如以下 REPL 示例所示:
scala> val x = 1
val x: Int = 1
scala> val s = "a string"
val s: String = a string
此功能称为类型推断,它是帮助保持代码简洁的好方法。 您还可以显式声明变量的类型,但这通常不是必需的:
如您所见,该代码看起来不必要地冗长。
Control structures
这是 Scala 控制结构的快速浏览。
if/else
Scala 的 if/else 控制结构与其他语言类似:
if (test1) {
doA()
} else if (test2) {
doB()
} else if (test3) {
doC()
} else {
doD()
}
然而,与Java和许多其他语言不同的是,if/else构造返回一个值,因此,除了其他功能外,你可以将它用作一个三元操作符:
val x = if (a < b) a else b
match expressions
Scala 有一个match
表达式,它最基本的用法就像一个 Java switch
语句:
val result = i match {
case 1 => "one"
case 2 => "two"
case _ => "not 1 or 2"
}
匹配表达式不仅限于整数,它可以用于任何数据类型,包括布尔值:
val booleanAsString = bool match {
case true => "true"
case false => "false"
}
下面是一个 match
被用作方法体的例子,并且匹配许多不同的类型:
def getClassAsString(x: Any):String = x match {
case s: String => s + " is a String"
case i: Int => "Int"
case f: Float => "Float"
case l: List[_] => "List"
case p: Person => "Person"
case _ => "Unknown"
}
强大的匹配表达式是 Scala 的一大特色,我们将在本书后面分享更多示例。
try/catch
Scala 的 try/catch 控制结构可让您捕获异常。 它类似于Java,但其语法与匹配表达式一致:
try {
writeToFile(text)
} catch {
case fnfe: FileNotFoundException => println(fnfe)
case ioe: IOException => println(ioe)
}
for loops and expressions
Scala for
循环——我们在本书中通常将其写为 for 循环——看起来像这样:
for (arg <- args) println(arg)
// "x to y" syntax
for (i <- 0 to 5) println(i)
// "x to y by" syntax
for (i <- 0 to 10 by 2) println(i)
您还可以将 yield
关键字添加到 for 循环以创建产生结果的 for 表达式。 这是一个 for 表达式,它将序列 1 到 5 中的每个值加倍:
val x = for (i <- 1 to 5) yield i * 2
这是另一个遍历字符串列表的 for 表达式:
val fruits = List("apple", "banana", "lime", "orange")
val fruitLengths = for {
f <- fruits
if f.length > 4
} yield f.length
因为 Scala 代码通常是有意义的,我们可以想象你可以猜出这段代码是如何工作的,即使你之前从未见过 for 表达式或 Scala 列表。
while and do/while
Scala 也有 while
和 do/while
循环。 这是它们的一般语法:
// while loop
while(condition) {
statement(a)
statement(b)
}
// do-while
do {
statement(a)
statement(b)
}
while(condition)
Classes
这里是一个Scala 类的例子:
class Person(var firstName: String, var lastName: String) {
def printFullName() = println(s"$firstName $lastName")
}
这是您使用该类的方式
val p = new Person("Julia", "Kern")
println(p.firstName)
p.lastName = "Manes"
p.printFullName()
请注意,无需创建“get”和“set”方法来访问类中的字段。
作为一个更复杂的例子,这里有一个 Pizza 类,你将在本书后面看到:
class Pizza (
var crustSize: CrustSize,
var crustType: CrustType,
val toppings: ArrayBuffer[Topping]
) {
def addTopping(t: Topping): Unit = toppings += t
def removeTopping(t: Topping): Unit = toppings -= t
def removeAllToppings(): Unit = toppings.clear()
}
在该代码中,ArrayBuffer
就像 Java 的 ArrayList
。 CrustSize
、CrustType
和 Topping
类未显示,但您可能无需查看这些类就可以理解该代码的工作原理。
Scala methods
就像其他 OOP 语言一样,Scala 类也有方法,这就是 Scala 方法语法的样子:
def sum(a: Int, b: Int): Int = a + b
def concatenate(s1: String, s2: String): String = s1 + s2
您不必声明方法的返回类型,因此如果您愿意,可以像这样编写这两个方法是完全合法的:
def sum(a: Int, b: Int) = a + b
def concatenate(s1: String, s2: String) = s1 + s2
这就是您调用这些方法的方式:
val x = sum(1, 2)
val y = concatenate("foo", "bar")
你可以用方法做更多的事情,比如为方法参数提供默认值,但现在这是一个好的开始。
Traits
Scala 中的特性非常有趣,它们还可以让您将代码分解为小的模块化单元。 为了演示特征,这里有一个本书后面的例子。 鉴于这三个特点:
trait Speaker {
def speak(): String // has no body, so it’s abstract
}
trait TailWagger {
def startTail(): Unit = println("tail is wagging")
def stopTail(): Unit = println("tail is stopped")
}
trait Runner {
def startRunning(): Unit = println("I’m running")
def stopRunning(): Unit = println("Stopped running")
}
您可以创建一个 Dog 类来扩展所有这些特征,同时为 speak 方法提供行为:
class Dog(name: String) extends Speaker with TailWagger with Runner {
def speak(): String = "Woof!"
}
类似地,这是一个 Cat 类,它展示了如何覆盖多个 trait 方法:
class Cat extends Speaker with TailWagger with Runner {
def speak(): String = "Meow"
override def startRunning(): Unit = println("Yeah ... I don’t run")
override def stopRunning(): Unit = println("No need to stop")
}
如果代码是有意义的——太好了,你对trait很满意!如果没有,不要担心,我们会在后面的书中详细解释。
Collections classes
如果您是从Java学习Scala的,并且已经准备好真正投入学习Scala,那么在Scala中使用Java集合类是可能的,有些人在熟悉Scala的同时也会这样做几个星期或几个月。但是强烈建议您尽快学习基本的Scala集合类——List
、ListBuffer
、Vector
、ArrayBuffer
、Map
和Set
。Scala集合类的一个巨大好处是,它们提供了许多功能强大的方法,您希望尽快开始使用这些方法来简化代码。
Populating lists
有时创建填充数据的示例列表会很有帮助,Scala 提供了许多填充列表的方法。 这里仅仅是少数:
val nums = List.range(0, 10)
val nums = (1 to 10 by 2).toList
val letters = ('a' to 'f').toList
val letters = ('a' to 'f' by 2).toList
Sequence methods
虽然您可以使用许多顺序集合类 — Array
、ArrayBuffer
、Vector
、List
等 — 让我们看一些您可以使用 List
类做什么的示例。 鉴于这两个列表
val nums = (1 to 10).toList
val names = List("joel", "ed", "chris", "maurice")
这是一个 foreach
方法:
scala> names.foreach(println)
joel
ed
chris
maurice
这是一个filter
然后是一个foreach
方法
scala> nums.filter(_ < 4).foreach(println)
1
2
3
这里有一些关于Map
方法的例子
scala> val doubles = nums.map(_ * 2)
doubles: List[Int] = List(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)
scala> val capNames = names.map(_.capitalize)
capNames: List[String] = List(Joel, Ed, Chris, Maurice)
scala> val lessThanFive = nums.map(_ < 5)
lessThanFive: List[Boolean] = List(true, true, true, true, false, false, false, false, false, false)
即使没有任何解释,您也可以看到 map 是如何工作的:它将您提供的算法应用于集合中的每个元素,为每个元素返回一个新的、转换后的值。
如果您准备好了解最强大的集合方法之一,请使用 foldLeft:
scala> nums.foldLeft(0)(_ + _)
res0: Int = 55
scala> nums.foldLeft(1)(_ * _)
res1: Int = 3628800
一旦您知道 foldLeft
的第一个参数是seed value,您就可以猜测第一个示例得出nums
中数字的总和,而第二个示例返回所有这些数字的乘积。
Scala 集合类有很多(很多!)更多方法可用,其中许多方法将在接下来的集合课程中演示,但希望这能让您了解它们的功能。
Tuples
元组让您可以将不同的元素集合放在一个小容器中。 一个元组可以包含 2 到 22 个值,并且所有值都可以有不同的类型。 例如,这是一个包含三种不同类型(Int
、Double
和 String
)的元组:
(11, 11.0, "Eleven")
这被称为 Tuple3,因为它包含三个元素。
元组在很多地方都很方便,例如您可能会在其他语言中使用临时类。 例如,您可以从方法返回一个元组而不是返回一个类:
def getAaplInfo(): (String, BigDecimal, Long) = {
// get the stock symbol, price, and volume
("AAPL", BigDecimal(123.45), 101202303L)
}
然后你可以将方法的结果分配给一个变量:
val t = getAaplInfo()
一旦你有了一个元组变量,你就可以通过数字访问它的值,前面是下划线:
t._1
t._2
t._3
REPL 演示了访问这些字段的结果:
scala> t._1
res0: String = AAPL
scala> t._2
res1: scala.math.BigDecimal = 123.45
scala> t._3
res2: Long = 101202303
元组的值也可以使用模式匹配来提取。 在下一个示例中,元组内的字段被分配给变量symbol
、price
和volume
:
val (symbol, price, volume) = getAaplInfo()
REPL 再次演示了结果:
scala> val (symbol, price, volume) = getAaplInfo()
symbol: String = AAPL
price: scala.math.BigDecimal = 123.45
volume: Long = 101202303
当你想快速(和临时)将一些东西组合在一起的时候,元组是很好的。 如果您注意到多次使用相同的元组,那么声明一个专用的 case 类可能会很有用,例如:
case class StockInfo(symbol: String, price: BigDecimal, volume: Long)
What we haven’t shown
虽然这是 Scala 的旋风式介绍,大约有十页印刷,但还有很多东西我们还没有展示,包括:
- 字符串和内置数字类型
- 包装和进口
- 如何在 Scala 中使用 Java 集合类
- 如何在 Scala 中使用 Java 库
- 如何构建 Scala 项目
- 如何在 Scala 中执行单元测试
- 如何编写 Scala shell 脚本
- Maps、Sets 和其他集合类
- 面向对象编程
- 函数式编程
- 与并发特性
- 更多的 …
如果您喜欢到目前为止所看到的内容,我们希望您会喜欢本书的其余部分。
以上是关于Scala学习之Scala快速入门的主要内容,如果未能解决你的问题,请参考以下文章