本章将介绍scala语言的基础内容
尝试在浏览器中使用Scala
你可以使用ScalaFiddle在浏览器中运行Scala。这是一种简单、零基础的方式来实验Scala代码段。
- 访问网址 https://scalafiddle.io.
- 复制
println("Hello, world!")
进左边的面板
- 点击Run. 在右边的面板就会显示输出
表达式
表达式是可以被计算的语句:
1+1
你可以用 println 对表达式的结果输出:
println(1) // 1 println(1 + 1) // 2 println("Hello!") // Hello! println("Hello," + " world!") // Hello, world!
【注:输出结果:】
1
2
Hello
Hello, world
值
你可以用关键字 val 来命名表达式的结果
val x = 1 + 1 println(x) //2
【注:输出结果:】
2
像 x 这种用来命名结果的,我们称之为值。引用值不会重新计算表达式。
值不能被重新定义赋值. 【注:val修饰的变量是被final修饰过了】
x = 3 // 无法编译通过.
值的类型描述可以被省略,编译器会自行推断出来。当然也可以显式地声明出来
val x: Int = 1 + 1
注意声明类型时,Int是跟在命名 x 后的,用一个 : 表示这个值的类型
变量
变量跟值类似,但是变量可以重新赋值定义。你可以通过 var 关键字来声明一个变量
var x = 1 + 1 x = 3 // 这里因为用var声明,所以可以编译通过 . println(x * x) // 9
跟值一样,变量的类型也可以被省略或者被推断,也可以被显式的指定出来
var x: Int = 1 + 1
【注:这里解释下 scala是一个静态语言,静态语言意味着变量一旦类型定下就不可以改变。虽然变量和值都是可以通过编译器进行类型推断的,但是类型是不能被修改的。例如:
var a = 10 //变量a 是Int类型,这是编译器推断的结果 a = "hello" //这里编译会报错,因为a的类型已经是Int,再重新赋予字符串时就会类型错误
】
代码块
你可以通过 {} 包围的方式来组合表达式。我们称之为代码块。
该块的最后一个表达式的结果也是这个代码块的最终结果:
println({ val x = 1 + 1 x + 1 }) // 3
函数
函数是具有参数、并且能传递参数值的表达式。
你可以定义一个匿名函数(例如 一个没有名称的函数),这个函数的作用是给一个整型的值加1
(x: Int) => x + 1
在 => 左边是一个参数的列表,右边则是一个包含参数的表达式
当然你也可以命名这个函数
val addOne = (x: Int) => x + 1 println(addOne(1)) // 2
一个函数可以有多个参数:
val add = (x: Int, y: Int) => x + y println(add(1, 2)) // 3
当然它也可以没有参数:
val getTheAnswer = () => 42 println(getTheAnswer()) // 42
方法
方法外观和行为都非常像函数,但是它们之间有一些细微的区别。
方法是通过 def 关键字定义, def 后面跟着一个名字,然后紧接着一个参数列表,一个返回结果,和一个代码体
def add(x: Int, y: Int): Int = x + y println(add(1, 2)) // 3
注意方法的返回类型声明是在参数列表后面用一个 : 接起来的
一个方法可以传递多个参数列表:
def addThenMultiply(x: Int, y: Int)(multiplier: Int): Int = (x + y) * multiplier println(addThenMultiply(1, 2)(3)) // 9
或者根本就没有参数列表:
def name: String = System.getProperty("user.name")
println("Hello, " + name + "!")
方法和函数还有一些其他区别,但是就目前为止,你还是可以认为方法就是类似于函数的东西。
方法也可以有多行的表达式:
def getSquareString(input: Double): String = { val square = input * input square.toString } println(getSquareString(2.5)) // 6.25
方法的代码体内的最后一行表达式的结果也就是方法的返回结果.(Scala有返回关键字,但是用的很少) 【注:函数和方法的都是以最后一个变量或表达式作返回结果,你可以认为就是在最后一行代码加隐式的加了一个return】
类
你可以用 class 关键字定义一个类,类后面接一个参数列表 就是它的有参构造类
class Greeter(prefix: String, suffix: String) { def greet(name: String): Unit = println(prefix + name + suffix) }
greet 方法的返回结果是 Unit ,这表明这个方法没有任何返回值。 类似于Java和C中的 void。(有一个小区别是,由于Scala的每个表达式都必须返回值,因此Unit实际上也是一个单例的值,只不过这个值是 空(),不包含任何信息的值)
val greeter = new Greeter("Hello, ", "!") greeter.greet("Scala developer") // Hello, Scala developer!
我们会在后面的章节对类进行一个深入的讲解
Case 类
Scala有一个特殊的类,叫做 case 类。默认的情况下,case类的实例是不可变的,且它们是通过值比较的(区别与普通的类,普通的类是通过引用进行比较的)。这些特性让case 类在模式匹配中非常的有优势。
你可以定义case类通过 case class 关键字声明:
case class Point(x: Int, y: Int)
你也可以不用new关键字就可以实例化一个case类对象
val point = Point(1, 2) val anotherPoint = Point(1, 2) val yetAnotherPoint = Point(2, 2)
case 类是通过值进行比较的,而不是通过引用
if (point == anotherPoint) { println(point + " and " + anotherPoint + " are the same.") } else { println(point + " and " + anotherPoint + " are different.") } // Point(1,2) and Point(1,2) are the same. if (point == yetAnotherPoint) { println(point + " and " + yetAnotherPoint + " are the same.") } else { println(point + " and " + yetAnotherPoint + " are different.") } // Point(1,2) and Point(2,2) are different.
关于case 类还有很多需要介绍,我们会在后面的章节继续深入介绍,相信你会爱上它们的
Objects 伴生对象
Objects 伴生对象是它们自己定义的一个单例实例。你可以把它认为是一个类自身携带的一个单例
你可以用 object 关键字来定一个伴生对象objects
object IdFactory { private var counter = 0 def create(): Int = { counter += 1 counter } }
你可以引用对象的名称来直接访问它的内部
val newId: Int = IdFactory.create() println(newId) // 1 val newerId: Int = IdFactory.create() println(newerId) // 2
我们将在后面的章节来详细介绍它
特性 Traits
特性是一个包含某些属性和方法的抽象数据类型。在Scala继承中,一个类只能被允许继承一个其他类,但是它可以被继承多个特性。
你可以通过 trait 关键字来定义特性:
trait Greeter {
def greet(name: String): Unit
}
特性可以有一个默认的实现:
trait Greeter { def greet(name: String): Unit = println("Hello, " + name + "!") }
你可以使用一个 extends 关键字来继承一个特性,并且用 override 关键字来重写它的实现体
class DefaultGreeter extends Greeter class CustomizableGreeter(prefix: String, postfix: String) extends Greeter { override def greet(name: String): Unit = { println(prefix + name + postfix) } } val greeter = new DefaultGreeter() greeter.greet("Scala developer") // Hello, Scala developer! val customGreeter = new CustomizableGreeter("How are you, ", "?") customGreeter.greet("Scala developer") // How are you, Scala developer?
这里的 DefaultGreeter 只继承了一个特性,但实际上它可以继承多个特性。
我们将在后面的章节深入介绍特性
Main 方法
main 方法是Scala程序的入口点。Java虚拟机也需要一个包含一个String数组参数的 main 方法。
使用一个 伴生对象object,你可以像如下这样定义一个main 方法:
object Main { def main(args: Array[String]): Unit = println("Hello, Scala developer!") }