因为有个项目(网游服务器)用到了scala,第一次接触感觉这门语言非常犀利,所以把做项目的过程中积累的这个语言相关的知识点整理下做个笔记。内容不分先后顺序,前后基本没有逻辑,就是简单的知识点块。我之前是做java的,所以有些比较都是针对java。
先介绍几个重要链接:
scala官网 http://www.scala-lang.org/
scalaAPI http://www.scala-lang.org/api/current/index.html
scala中文社区 http://www.scala-china.net/discuz/forum.php
class 和 object 的区别:
object是class的伴随对象。 scala中没有static关键字,所以java中static类型的变量、方法都要放在scala的object里非static的放在class里。
只有一个参数的函数可以使用下面这样的表达式来表示:
df format now
其实就是下面的这个冗长的表达式的简洁写法
df.format(now)
def testFunc1() {//没有返回值 默认为Unit 可以省略“=”
...
}
def testFunc2():Int = {//有一个整形的返回值,“=”不能省略
...
}
**注意:**def a = 1 ,这里是声明了一个函数返回一个固定值1,而不是定义了一个变量。
class Test extends Actor with ActorLogging{
def receive={
...
}}
如果要在 Actor 中继续创建子 Actor,需要使用内置的 ActorContext(implicit) 对象
context.actorOf(Props[children], name = "children")
”Alice“-> 10 生成一个 (“Alice”, 10)
0 to (-10, -1)或者0 to -10 by -1
def scalaFiles =
for(
file <- filesHere
if file.isFile
if file.getName.endsWith(".scala")
) yield file
x map .. 相当于 x.map{…}
相当于把x中的所有数据遍历一遍,每一个值都执行大括号内的操作
也可以取Future类型数据中的值
for循环中带左箭头
for(i ← start until start+10 ){
//I从start值开始,到start+10结束
}
val twoThree = List(2, 3)
val oneTwoThree = 1 :: twoThree
当以:为结尾时,调用翻转 前在后,后再前
val seq1 = Seq(1,2,3) //1,2,3
val seq2 = Seq1 :+ 4 //1,2,3,4
val seq3 = 4 +: Swq1 //4,1,2,3
这种类编译器会自动做如下事:
- 创建同名构造器和apply方法,class() 取代了new class()
- 以参数名为名称创建构造函数的参数,如 class(a:Int,b:String)相当于有两个参数a,b class.a, class.b就能直接调用
- 构造了toString,hashCode,equals的实现
- 添加一个.copy方法,可以创建一个可修改的拷贝。class.copy(a=“a1”)
val t = testDef(i=>”111”+i)
def testDef(body:(Int=>String))={
body(123*3)
}
println(t) 结果是 “111369”
上面的i=>”111”+i 是一个匿名函数,在testDef中它的名字叫body.
body(123*3)相当于把123*3的值带入到了“ body”函数中
- 函数的可选参数
method(i:Int = 1, s:String)//i就是可选参数(不填的话就取默认值1),s就是必填参数
val t @ a_val_that_very_long=3
case t @ (“a_val_that_very_long1" | “a_val_that_very_long2” | “a_val_that_very_long3”) => pringln(t)
sealed trait PiMessage
case object Calculate extends PiMessage
case class Work(start: Int, nrOfElements: Int) extends PiMessage
case class Result(value: Double) extends PiMessage
case class PiApproximation(pi: Double, duration: Duration)
for{
a<-Future(xxx)
b<-Future(xxx)
c<-Future(xxx)
}yield{
do(a)
do(b)
do(c)
}
//abc三个future全部返回后才会之行yield里面的操作
//可以用来将多个Actor的回应组合成一个单独的计算而不调用Await.reuslt
code1:
val milkFuture = future{ getMilk() }
val meatFuture = future{ getMeat() }
for{
milk <- milkFuture
meat <- meatFuture
} yield{
println(milk)
println(meat)
}
code2:
for{
milk <- future{ getMilk() }
meat <- future{ getMeat() }
} yield{
println(milk)
println(meat)
}
//这两段代码的区别是, code1中getMilk,getMeat是并行的,code2中,是按先后顺序之行!
val opt1 = Option(10)
val opt2 = Option(20)
val opt3 = None
for{
o1 <- opt1
o2 <- opt2
o3 <- opt3
}{
println(o1)
println(o2)
println(o3)
}
//结果是“什么都不会打印!!!”,在for的第一个结构体中,如果有任何一个元素是None,则第二个结构体中的任何代码都不会执行,不执行,不!
Array: val arry1 = Array[Int](12) val arry = new Array[Int](12) //前者数组长度为1,后者长度为12
class Rational(n:Int, d:Int){
require(d!=0)//自动载入,无须import,创建对象不满足时会抛异常
override def toString = n+”/“+d
}
指的是在函数体内调用了外部的变量,定义这个函数的过程是将这个自由变量捕获而构成的一个封闭的函数。 但这个自由变量变化时,scala的闭包能捕获到这个变化。 闭包用于创建函数的函数中,被创建的函数是闭包。重复参数
参数类型与最后一个参数一致,def echo(arg0:String,arg1:Int ),数组做参数时可这样调用echo(“abc”,intarray:_)柯里化(curring)
指将接受多个参数的函数,转化为接收 一个单一参数的函数并且返回 接受余下参数 且返回结果的新函数的技术。如果函数只有一个参数,可以用{}代替(). println{“123”}和println(“123”)是一样的 传值参数和传名参数
def func1(func2:()=>Boolean){…} 传值参数调用时 func1( ()=>5>3 )
def func1(func2: => Boolean){…} 传名参数调用时 func1(5>3)
java里
String s1 = “abc”;
String s2 = new String(“abc”);
s1==s2 结果为false
因为”abc”本身就是一个字符串常量对象,而第二句代码里其实生成了两个对象:”abc” 和 new String(xxx). 对于对象间使用”==“,表示对比是不是指向同一个对象。
scala中
==会自动适应变量类型,如果是值类型,就对比值。如果是引用类型,就视为equals方法的别名。 如果想比较引用是否相等就需要用 eq 或者 neqflatmap 和 map的区别
假如一个List使用map后返回 List(1,2,3,List(4,5)) 那用flatmap后就会返回 List(1,2,3,4,5),flatmap返回的是扁平的list