Scala控制结构和函数

基础知识

  • scala中没有静态方法,不过它有个类似的特性,叫做单利对象。通常一个类对应有一个伴生对象,其方法就跟java中的静态方法一样。

  • 不带参数的scala方法通常不使用圆括号。

  • aplly方法 举个例子,如果调用

BigInt("12345678")

其实是如下语句的简写:

BigInt.aplly("12345678")

这个语句产生一个新的BigInt对象,不需要使用new,这是scala风格的构建对象的方式。 再比如,使用Array(1,2,3)返回一个数组,其实也是用的Array的半生对象的apply方法。

  • 类型转换 在scala中,我们使用方法,而不是强制类型转换来做数值类型之间的转换。
99.44.toInt             //99
99.toChar               //c
"99.33".toDouble        //99.33
  • ++/--操作符 scala拒绝提供自增/自减操作符,原因是++方法并不是那么简单实现的,scala的设计者认为不值得为少按一个键额外增加一个特例。

  • 控制台输入

val name = readLine("please input your name : \n")
val age= readInt()
//readDouble,readByte,readShort,readLong,readFloat

if结构

scala的if/else表达式有值,这个值就是跟在if/else后面表达式的值

val s = if(x>0) 1 else -1

在scala中引入了一个特殊的类Unit,你可以把它当做“无有用值”的占位符。可以跟java中的void类比。

另外scala不提供switch语句,但是提供了更加强大的模式匹配机制。

块表达式和赋值

在scala中,{}块包含的一个语句块的最后一个表达式的值作为该语句块的值,这个特性对于那种对某个val的初始化需要分多步完成的情况很有用。

另外一点scala跟c++和java不同的地方是,scala的赋值语句的值是Unit类型的,因此

x=y=1

在java中,这个赋值语句是有意义的,即将x,y都赋值为1,而在scala中,y被赋值为1,x则被赋值为Unit,这几乎不会是你想做的事情。

循环

for(i <- 1 to n)
for(i <- 1 util array.length)

你可以为for循环用变量 <- 表达式的形式提供多个生成器,用分号将它们隔开。每个生成器可以带一个守卫,以if开头的布尔表达式:

for(i <- 1 to 3 if i ! = 2;j <- 1 to 3 if i != j) print((10*x+y)+" ")
for(i <- 1 to 10) yield i % 3 //Vector(1,2,0,1,2,0,1,2,0)
for(i <- "Hello";c <- 0 to 1) yield (c+i).toChar //"HIeflmlmop"

yield称为生成器,它的主要作用是记住每次迭代中的有关值,并逐一存入到一个数组中。用法如下:

for (子句) yield {变量或表达式}

在for循环表达式里,也可以使用任意多的定义,引入可以在循环中使用的变量:

for(i <- 1 to 3; from = 4-i;j <- from to 3) print((10*i+j)+" ")

函数

def fun(x : Int) = if(x>=0) x else -x

如果函数不是递归的,你不需要指定返回类型,scala可以通过返回值的类型推断函数的返回类型。

def fac(n : Int) : Int = if(n<=0) 1 else n*fac(n-1)

上面的例子里,如果没有返回类型,scala无法校验n*fac(n-1)的类型。

变长参数

def sum(args : Int*)={
    dosomething
}
val s = sum(1,2,3,4,5)

如果你已经有一个值的序列,则不能直接将它传入,例如下面的例子是错误的:

val s = sum(1 to 5)

解决这个问题的办法是告诉编译器你希望这个参数被当成参数序列来处理,追加:_*

val s = sum(1 to 5:_*)

过程

不返回值的函数称为过程,我们调用它仅仅是为了它的副作用。

lazy value

延迟加载的值,只有当我们真正用到它时才会初始化,这对于开销较大的初始化语句来说非常有用。

val words = scala.io.Source.fromFile("/urs/share/words").mkString
lazy val words = scala.io.Source.fromFile("/urs/share/words").mkString

如果路径是错误的,那么用val初始化直接报错,会提示文件找不到,而lazy val此时是不会报错的,如果以后某个时候使用到words这个变量,才会报错。

异常

var in = new URL("http://horstmann.com").openStream()
try{
    process(in)
    }catch{
    case _ : MalformedURLException => println("bad URL : "+url)
    case ex : IOException => ex.printStackTrace()
}finally{
    in.close()
}

如果不需要使用捕获的异常对象,可以使用_来代替变量名。 跟c++/java一样,更具体的异常应该放在前面。

Comments !