Scala吸收了收并继承了多种语言中的优秀特性,另一方面也没有抛弃Java这个强大的平台,它可以运行在 Java 虚拟机之上,能够轻松地与Java互联互通。与Java不同的是,
Scala既支持面向对象的特性,又支持函数式编程,被称为是Java的替代语言,是更好的Java,下面开始学习这一强大的语言。

Scala和Java比较

在Scala中

  1. 所有类型都是对象
  2. 函数是对象
  3. 支持Domain specific language (DSL)领域特定语言
  4. 特质(Trait)
  5. 闭包(Closure),嵌套函数
  6. Erlang支持的并发设计
  7. 类型推导

基础语法

表达式

scala> 1 + 1
res0: Int = 2

res0是解释器自动创建的变量名称,指代表达式计算的结果,是Int类型的,值为2。在scala几乎一切都是表达式。

变量和值

可以将表达式赋给一个或者不变量(val)–值或者变量(var)

scala> val two = 1 + 1
two: Int = 2

如果需要以后修改这个名称和结果的绑定,需要使用var(变量),大部分的情况下用val的情况居多。

scala> var name = "zhaohongxuan"
name: java.lang.String = zhaohongxuan

scala> name = "zhaoxiaoxuan"
name: java.lang.String = zhaoxiaoxuan

函数

使用def关键字来创建函数

scala> def addOne(m: Int): Int = m + 1
addOne: (m: Int)Int

调用函数:

scala> val three = addOne(2)
three: Int = 3

在scala中,需要为函数参数制定类型的签名。但是,如果函数不带参数,括号可以省略。

scala> def three() = 1 + 2
three: ()Int

scala> three()
res2: Int = 3

scala> three
res3: Int = 3

匿名函数

创建匿名函数

scala> (x: Int) => x + 1
res2: (Int) => Int = <function1>

这个函数的作用是给名为x的变量加1.

scala> res2(1)
res3: Int = 2

也可以传递匿名函数

scala> val addOne = (x: Int) => x + 1
addOne: (Int) => Int = <function1>

scala> addOne(1)
res4: Int = 2

如果函数中表达式很多,可以用花括号{}来格式化代码、

scala> { i: Int =>
    println("hello world")
    i * 2
}
res0: (Int) => Int = <function1>

部分应用(Partial application)

可以使用下划线_部分应用一个函数,结果是得到另一个函数。

定义一个add函数

scala> def add(m: Int, n: Int) = m + n
add: (m: Int,n: Int)Int

将add函数部分应用得到一个新的匿名函数

scala> val add2 = add(2, _:Int)
add2: (Int) => Int = <function1>

scala> add2(3)
res50: Int = 5

可变长度参数

这是一种特殊的语法,可以向方法传入任意多个同类型的参数。比如给传入的参数的首字母进行大写的操作。

def capitalizeAll(args: String*) = {
  args.map { arg =>
    arg.capitalize
  }
}

scala> capitalizeAll("zhaoxiaoxuan", "douxiaonna")
res2: Seq[String] = ArrayBuffer(Zhaoxiaoxuan, Douxiaonna)

类、继承与特质

scala> class Calculator {
     |   val brand: String = "HP"
     |   def add(m: Int, n: Int): Int = m + n
     | }
defined class Calculator

scala> val calc = new Calculator
calc: Calculator = Calculator@e75a11

scala> calc.add(1, 2)
res1: Int = 3

scala> calc.brand
res2: String = "HP"

这个计算器类展示了在类中使用def定义方法,和使用val定义字段。其中方法就是可以可以访问类状态的函数

构造函数

构造函数不是特殊的方法,他们是除了类的方法定义之外的代码。

class Calculator(brand: String) {
  //构造函数
  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
}

使用构造函数来构造一个实例:

scala> val calc = new Calculator("HP")
calc: Calculator = Calculator@1e64cc4d

scala> calc.color
res0: String = black

在上面的例子中,颜色的值就是绑定在一个if/else表达式上的。Scala是高度面向表达式的:大多数东西都是表达式而非指令。

继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14

class Point(xc: Int, yc: Int) {
val x: Int = xc
val y: Int = yc
def move(dx: Int, dy: Int): Point =
new Point(x + dx, y + dy)
}
class ColorPoint(u: Int, v: Int, c: String) extends Point(u, v) {
val color: String = c
def compareWith(pt: ColorPoint): Boolean =
(pt.x == x) && (pt.y == y) && (pt.color == color)
override def move(dx: Int, dy: Int): ColorPoint =
new ColorPoint(x + dy, y + dy, color)
}

ColorPoint继承了Point中所有的成员,包括x,y包括move方法。

子类ColorPoint增加了一个新的方法compareWith
Scala允许对成员定义进行覆盖(Override),在这个例子中,我们在子类中用move方法覆盖了的父类的move方法,当然在子类中可以使用super关键字来调用父类的move方法。

抽象类

定义一个抽象类,它定义了一些方法但没有实现它们。取而代之是由扩展抽象类的子类定义这些方法。抽象类不能创建实例。

scala> abstract class Shape {
     |   def getArea():Int    // subclass should define this
     | }
defined class Shape

scala> class Circle(r: Int) extends Shape {
     |   def getArea():Int = { r * r * 3 }
     | }
defined class Circle

scala> val s = new Shape
<console>:8: error: class Shape is abstract; cannot be instantiated
       val s = new Shape
           ^
scala> val c = new Circle(2)
c: Circle = Circle@65c0035b

特质

特质是一些字段和行为的集合,可以扩展或者混入(Mixin)你的类中。

trait Car {
  val brand: String
}

trait Shiny {
  val shineRefraction: Int
}
class BMW extends Car {
  val brand = "BMW"
}

通过with关键字,一个类可以扩展多个特质:

class BMW extends Car with Shiny {
  val brand = "BMW"
  val shineRefraction = 12
}

本站由 Hank Zhao 使用 Stellar 主题创建。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
本站总访问量