一、定义变量
Scala 为定义变量提供了两种语法。使用 val定义常量,一经定义后,该变量名不能被重新赋值。使用 var定义变量,可被重新赋值。
package com.sunsharing /** * Created by Administrator on 2016/1/24. */ object Variable { var i=0; val j=0; i = 999; j = 888; }
报错:
二、定义函数
函数的定义也非常简单,使用关键字 def,后跟函数名和参数列表,如果不是递归函数可以选择省略函数返回类型。Scala 还支持定义匿名函数,匿名函数由参数列表,箭头连接符和函数体组成。函数在 Scala 中属于一级对象,它可以作为参数传递给其他函数,可以作为另一个函数的返回值,或者赋给一个变量。在下面的示例代码中,定义的匿名函数被赋给变量 cube。匿名函数使用起来非常方便,比如 List对象中的一些方法需要传入一个简单的函数作为参数,我们当然可以定义一个函数,然后再传给 List对象中的方法,但使用匿名函数,程序看上去更加简洁。
package com.sunsharing /** * Created by Administrator on 2016/1/24. */ object ScalaStudy { // 定义函数 def square(x: Int): Int = x * x // 如果不是递归函数,函数返回类型可省略 def sum_of_square(x: Int, y: Int) = square(x) + square(y) def main(args: Array[String]): Unit = { println("平方和", sum_of_square(2, 3)) // 定义匿名函数 val cube = (x: Int) => x * x *x println("立方", cube(3)) // 使用匿名函数,返回列表中的正数 println("正数列表", List(-2, -1, 0, 1, 2, 3).filter(x => x > 0)) } }
运行结果:
(平方和,13) (立方,27) (正数列表,List(1, 2, 3))
与Java对比:
首先,函数体没有像 Java 那样放在 {}里。Scala 中的一条语句其实是一个表达式,函数的执行过程就是对函数体内的表达式的求值过程,最后一条表达式的值就是函数的返回值。如果函数体只包含一条表达式,则可以省略 {}。其次,没有显示的 return语句,最后一条表达式的值会自动返回给函数的调用者。
和 Java 不同,在 Scala 中,函数内部还可以定义其他函数。比如上面的程序中,如果用户只对 sum_of_square 函数感兴趣,则我们可以将 square 函数定义为内部函数,实现细节的隐藏。
三、流程控制语句
/** * if else 求绝对值 * @param n * @return */ def abs(n: Int): Int = if (n > 0) n else -n println(abs(-39)); /** * while 求和 * @param xs * @return */ def sum(xs: List[Int]) = { var total = 0 var index = 0 while (index < xs.size) { total += xs(index) index += 1 } total } println(sum(List(3, 4, -5, 54)));
四、使用递归对数列求和
/** * xs.head 返回列表里的头元素,即第一个元素 * xs.tail 返回除头元素外的剩余元素组成的列表 * 递归对函数求和 * @param xs * @return */ def recursionSum(xs: List[Int]): Int = if (xs.isEmpty) 0 else xs.head + recursionSum(xs.tail) println(recursionSum(List(3, 4, -5, 54)));
更为简便的方法
println(List(3, 4, -5, 54).foldLeft(0)((x0, x) => x0 + x))
该方法传入一个初始值 0,一个匿名函数,该匿名函数累加列表中的每一个元素,最终返回整个列表的和。使用上面的方法,我们甚至不需要定义额外的方法,就可以完成同样的操作。
五、模式匹配是Scala最广泛使用的功能之一,经过函数值和闭包。Scala中大力支持模式匹配处理消息。
1. 模式匹配包括替代的序列,每个开始使用关键字case。每个备选中包括模式和一个或多个表达式,如果模式匹配将被计算。一个箭头符号=>分开的表达模式。
object Match extends App{ def matchTest(x: Int): String = x match { case 1 => "one" case 2 => "two" case _ => "many" } println(matchTest(1)) println(matchTest(2)) println(matchTest(3)) println(matchTest(4)) }
运行结果:
one two many many
2. 使用case语句块定义一个函数,该函数映射整数字符串。匹配关键字提供应用函数(如模式匹配函数以上)为一个对象的一个方便的方法。
def matchTestAny(x: Any): Any = x match { case 1 => "one" case "two" => 2 case y: Int => "scala.Int" case _ => "many" } println(matchTestAny(1)) println(matchTestAny("two")) println(matchTestAny(3)) println(matchTestAny(4)) println(matchTestAny(List(1, 4, 5)))
运行结果:
one 2 scala.Int scala.Int many
3. 匹配使用case类
case classes是用于模式匹配与case 表达式指定类。这些都是标准类具有特殊修饰:case。
val alice = new Person("Alice", 25) val bob = new Person("Bob", 32) val charlie = new Person("Charlie", 32) for (person <- List(alice, bob, charlie)) { person match { case Person("Alice", 25) => println("Hi Alice!") case Person("Bob", 32) => println("Hi Bob!") case Person(name, age) => println("Age: " + age + " year, name: " + name + "?") } } case class Person(name: String, age: Int)
运行结果:
Hi Alice! Hi Bob! Age: 32 year, name: Charlie?
增加 case 关键字使编译器自动添加了许多实用的功能。关键字建议与模式匹配的情况下表达式的关联。
首先,编译器会自动转换的构造函数的参数为不可变的字段(vals)。val关键字是可选的。如果想可变字段,使用var关键字。因此,构造函数的参数列表现在更短。
其次,编译器自动实现equals, hashCode, 和toString方法的类,它使用指定为构造函数参数的字段。因此,不再需要自己的toString方法。
最后,还消失Person类的主体部分,因为没有需要定义的方法!
六、类是一个对象的蓝图。一旦定义一个类可以创建从类蓝图使用关键字new创建对象。
Scala中类对象中不可有静态变量和静态方法,但是提供了“伴侣对象”的功能:在和类的同一个文件中定义同名的Object对象:(须在同一文件中;main方法定义在Object对象中)
/** * Created by Administrator on 2016/1/24. */ class Person(val namec: String,val agec:Int) { var name = namec var age = agec def run(dAge:Int)={ println("name:"+name+"; age:"+(dAge+agec)) } }
可以扩展scala类以类似的方式,如在Java中的一样,但有两个限制:方法重载需要override关键字,只有主构造可以传递参数给基构造。
/** * Created by Administrator on 2016/1/24. */ class Boy(override val namec: String, override val agec:Int, val heightc:Int) extends Person(namec, agec){ var height = heightc def run(dAge:Int,dHeight:Int)={ println("name:"+namec+"; age:"+(dAge+agec)+"; height:"+(dHeight+heightc)) } }
extends子句有两种作用:它使类Location继承类Yiibai所有非私有成员,它使Location类作为Yiibai类的子类。 因此,这里的Yiibai类称为超类,而Location类被称为子类。扩展一个类,继承父类的所有功能,被称为继承,但scala允许继承,只能从一个唯一的类。
var boy = new Boy("jack", 12, 150); boy.run(4, 12) boy.run(34)
运行结果
name:jack; age:16; height:162 name:jack; age:46
单例对象
Scala比Java更面向对象,因为在Scala中不能有静态成员。相反,Scala有单例的对象。单例就是只能有一个实例,即,类的对象。可以使用关键字object代替class关键字,而不是创建单例。因为不能实例化一个单独的对象,不能将参数传递给主构造。前面已经看到全部采用单一对象,调用Scala的main方法的例子。
相关链接
http://www.yiibai.com/scala/scala_data_types.html
http://www.scala-lang.org/docu/files/ScalaTutorial.pdf?cm_mc_uid=58080025153914536211975&cm_mc_sid_50200000=1453627125