《Scala School》学习笔记-基础部分

Scala 中几乎一切都是表达式

变量与不变量

1
2
3
4
5
6
//不变量 val 修饰
val two = 1 + 1
//变量 var 修饰
var name = "steve"
name = "jobs"

函数

定义函数:

1
2
3
4
5
6
7
8
9
10
11
def addOne(m: Int): Int = m + 1
val three = addOne(2)
def three() = 1 + 2
three()
def timesTwo(i: Int): Int = {
println("hello world")
i * 2
}

匿名函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
(x: Int) => x + 1
res3: Int => Int = $$Lambda$1066/1463856502@40a84ea8
res3(1)
//将匿名函数保存为不变量进行使用:
val addOne = (x: Int) => x + 1
addOne(1)
//{}构造匿名函数, 将一个匿名函数作为参数传递时经常用到
{ i: Int =>
println("hello world")
i * 2
}

部分应用函数:

使用“_”应用一个函数,将得到另一个函数

1
2
3
4
5
6
7
8
//可以把它看作是一个没有命名的神奇通配符
def adder(m: Int, n: Int) = m + n
val add2 = adder(2, _:Int)
add2(10)
add2(10, 11)
//部分应用参数列表中的任意参数,而不仅仅是最后一个
val anotherAdd2 = adder(_:Int, 3)
anotherAdd2(10)

科里化函数:

1
2
3
4
5
6
7
8
9
def multiply(m: Int)(n: Int): Int = m * n
multiply(2)(3)
//填上第一个参数并且部分应用第二个参数
val timesTwo = multiply(2) _
timesTwo(3)
//对任何多参数函数执行柯里化
(adder _).curried

可变长度参数:

1
2
3
4
5
6
7
8
9
//可以向capitalizeAll函数传入任意多个同类型的参数
//在多个String上执行capitalize
def capitalizeAll(args: String*) = {
args.map { arg =>
arg.capitalize
}
}
capitalizeAll("rarity", "applejack")

1
2
3
4
5
6
7
8
class Calculator {
val brand: String = "HP"
def add(m: Int, n: Int): Int = m + n
}
val calc = new Calculator
calc.add(1, 2)
cala.brand

带构造函数的类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Calculator(brand: String) {
/**
* A constructor.
*/
val color: String = if (brand == "TI") {
"blue"
} else if (brand == "HP") {
"black"
} else {
"white"
}
// An instance method.
def add(m: Int, n: Int): Int = m + n
}
//通过构造器构造实例
val calc = new Calculator("HP")
calc.color

注意上面的add是实例方法,而val color: ..是constructor

函数与方法的区别:

1
2
3
4
5
6
7
8
9
class C {
var acc = 0
def minc = { acc += 1 }
val finc = { () => acc += 1 }
}
val c = new C
c.minc //这是方法,可以不带括号
c.finc() //c.finc返回的是一个函数,调用的话要加()

继承

1
2
3
class ScientificCalculator(brand: String) extends Calculator(brand) {
def log(m: Double, base: Double) = math.log(m) / math.log(base)
}

重载

1
2
3
class EvenMoreScientificCalculator(brand: String) extends ScientificCalculator(brand) {
def log(m: Int): Double = log(m, math.exp(1))
}

抽象类

1
2
3
4
5
6
7
8
9
abstract class Shape {
def getArea():Int // subclass should define this
}
class Circle(r: Int) extends Shape {
def getArea():Int = { r * r * 3 }
}
val c = new Circle(2)

Traits

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
trait Car {
val brand: String
}
trait Shiny {
val shineRefraction: Int
}
class BMW extends Car {
val brand = "BMW"
}
//一个类可以继承多个Traits
class BMW extends Car with Shiny {
val brand = "BMW"
val shineRefraction = 12
}

根据原文:

优先使用特质。一个类扩展多个特质是很方便的,但却只能扩展一个抽象类。

如果你需要构造函数参数,使用抽象类。因为抽象类可以定义带参数的构造函数,而特质不行。例如,你不能说trait t(i: Int) {},参数i是非法的。

在使用接口抽象的时候,最好使用trait来实现

泛型

1
2
3
4
5
trait Cache[K, V] {
def get(key: K): V
def put(key: K, value: V)
def delete(key: K)
}
坚持原创技术分享,您的支持将鼓励我继续创作!