scala基本语法:
特点:可扩展(面向对象,函数式编程);兼容java(类库调用,互操作);语法简洁(代码行短,类型推断,抽象控制);静态类型化(可检验,安全重构);支持并发控制(强计算能力,自定义其他控制结构);
函数式编程:
函数也是对象
声明与定义(赋值):
val,常量声明
val x:T
val x:T=e
var,变量声明
var x:T
var x:T=e
类型省略(默认类型)
val x=e
var x=e
声明省略(连续声明)
var x1,x2,x3:T=e等价于var xn:T=e
函数声明
def abc(xn:T):T*=e
“String”
‘char’
scala没有任何操作符,所有的操作符运算都是对方法(函数)的调用
如1+2实际上是调用了.+()这个方法1.+(2)
Scala标识符与命名:
首字符为字母,后续字符为任意字母和数字,可后接下划线_
首字符为操作符,后续字符为任意操作符
以反引号`括起来的任意字符串(除了反引号)
如return是保留字,标志为Do.return是非法的,但可以标志为Do.`return`
Scala是基于行的语言,分号和换行均可作为语句的结束;
编程规范:格式一致,层次缩进,合理命名
控制语句:
判断(if表达式): if(A) B;else C 当B为空时,可写成if(!A) C
if表达式能用以赋值: def min(x:Int,y:Int)= if(x>y) y else x 与下面代码等价
def min(x:Int,y:Int):Int={
var a=x
if(x>y) a=y
return a
}
循环(while/do): while(A) B
do B while(A)
枚举(for表达式): for(i <- e) E(i)
嵌套枚举: for(i <- e1;if A;j <- e2;if B) E(i,j)
返回集合:for(i <- “HELLO”)yield i
String:HELLO
for(i <- 1 to 2)yield i.toChar
Vector<?,?>
for(i <- “HELLO” ; j <- 1 to 2) yield (i+j).toChar
String:IJFGMNMNPQ
for(i <- 1 to 2;j <- “HELLO”) yield (i+j).toChar
Vector<I,J,F,G,M,N,M,N,P,Q>
匹配(match表达式)
a match{
case e1 => E1
case e2 => E2
case _=>...
}
异常处理(throw/try):try{函数体} catch{case..; case...} finally{A.close()}
输入输出:println(A) A可以是值,表达式等
Scala事实上无须使用return语句:对于函数来说,其默认返回值是最后出现的一个值,并非最后出现时,可在函数体后加上该值的标识符使之出现;
Scala数组: val A = new Array[T](N)
变长数组:val C = new ArrayBuffer[T]() 类型一致
toArray 转化成定长数组 toBuffer 转化为变长数组
Scala映射:Map((a1,b1),(a2,b2),(a3,b3))
获取:val d = Z.getOrElse(an,0)
可变映射的键值操作跟变长数组类似
值更新或增加新的键值对应:Y(an) = bn
Y += (a4->b4 , a5 -> b5) 增加键值对应
Y -= a4 删除键值对应
对于不可变映射,可以通过构造新的映射来增删其键值
val W=Z+(a4->b4 , a5 -> b5)
val V = W-(a4 -> b4 , a5 -> b5)
映射的枚举: for((i,j) <- Z) E(i,j)
互换映射的键值: for((i,j) <- Z) yield (j,i)
获取映射中键或值的集合: val e = Z.keySet
val f=Z.values
可以利用for表达式只枚举映射的键或值集合
映射是二元的元组,元组是不同类型的值的聚集
若干个单个的值包含在圆括号便构成元组:val g=(1,1.2,’A’)
利用方法 _1 _2 _3访问元组的组元
val h=g._1或 val h =g _1
元组把多个值捆绑在一起,是他们能同时被处理
Zip: 能把几个集合结合起来
val one = Array( ‘a’ , ‘b’ ,’c’ )
val two = Array( 1 ,2, 3)
val three = one.zip(two) 或 val three = one zip two
对应的就生成一个元素是二元的数组:Array[(Char,Int)] = Array((a,1),(b,2),(c,3))
val four=one.zip(two).toMap 或 val four = one zip two toMap
对应的生成一个以数组one为键,数组two为值的映射
Scala包:
包用来管理名称,包括名称的声明、定义等
能给已有的包增加名称或者创建新的包
包声明链scala.collection.mutable并不使scala与scala.collection可见
包声明链亦不对包含的包进行声明:如声明scala.collectio并不意味着声明scala.collection.mutable
引入包的全部成员:import scala.collection._
面向对象编程:
getter方法与setter方法的意义在于控制类中私有对象的数据
在类中可以通过重定义getter和setter方法获取、有限制的修改私有字段
class HELLOWORLD{
private var privatevalue1 = “HELLO”
var value2 = “WORLD”
def add(){ println(value1 + privatevalue2) }
def plus(m:Char)=value2 + m
def value1 = privatevalue1
def value1_=(newvalue1:String){
if(newvalue1.length > privatevalue1.length) privatevalue1 = newvalue1
}
}
辅助构造器的名称为this,在类中定义必须以一个主构造器或其他已定义的辅助构造器调用开始
Scala允许任何语法结构中嵌套任何语法结构
嵌套类:
class HELLOWORLD{
class HI{ .. }
}
对于同一个外部类,不同实例下的内部类是不同的
内部类可以调用外部类的成员,利用 外部类.this 或 指针 实现
class HELLOWORLD{pointto =>
var value2= “ “
class HI{
val value3 = HELLOWORLD.this.value2
var value4 = pointto.value2
}
}
object语法定义了某个类的单个实例
对象的构造器在该对象第一次被使用时调用
object语法结构与class大致相同,除了object不能提供构造器参数
通常使用单例对象的环境:
作为存放工具函数或常量的地方
共享单个不可变实例
利用单个实例协调某个服务
当一个单例对象存在同名类的时候,称为伴生对象
class HELLOWORLD{ .. }
object HELLOWORLD{ def NOW{ .. } }
类和其伴生对象可以互相访问私有属性,但必须存在同一个源文件中
类的伴生对象可以被访问,但并不在作用域中,如:
HELLOWORLD类必须通过HELLOWORLD.NOW调用伴生对象中的NOW方法,而不能直接用NOW来调用
apply方法用于有参数的伴生对象构造方法
重写规则:
重写def:
用val:利用val能重写超类没有参数的方法(getter)
用def:子类的方法与超类的方法重名
用var:同时重写getter、setter,只重写getter方法报错
重写val:
用val:子类的一个私有字段与超类的字段重名,getter方法重写超类的getter方法
重写var:
用var:且当超类的var是抽象的才能被重写,否则超类的var都会被继承
特质(多重继承): 类似于java的接口
trait 语法跟类相似,但不能拥有构造参数
特质混入顺序越靠后越先执行
高级特性之抽象化:
头等函数:
def sum(f:Int=>Int,a:Int,b:int):Int=
if(a<b) 0 else f(a)+sum(f,a+1,b)
def f1(a:Int) = a
def sum1(a:Int,b:Int):Int=sum(f1,a,b)
在Scala中,函数能作为参数进行传递,函数能调用满足参数要求的不同函数作为参数
匿名函数:(x1:T1,x2:T2,...) => E
def sum4(f:Int=>Int)=(Int,Int) => Int={
def sum5(a:Int,b:Int):Int=sum(f,a,b) ; sum5 }
柯里化:将多参函数变成多步函数(后一个参数传入前一个返回函数中)
def A(a:T1,b:T2,c:T3,d:T4) = E 等价于 def A(a:T1)(b:T2)(c:T3)(d:T4) = E
模式匹配:正则匹配,类型匹配
样例类:
封闭类:使样例类的超类被封闭(sealed),封闭类除类定义文件外不能添加子类
sealed abstract class Expr
case class Number(n:Int) extends Expr
case class Sum(e1 : Expr, e2 : Expr) extends Expr
case class Mul( e1 : Expr , e2 : Expr ) extends Expr
偏函数:把参数模式匹配
类型参数:
泛型:类、特质、函数、方法可带有类型参数
def getType(a:Any)
//a是Any类型
def getType[T](a:T)
//a是泛型,getType是泛型函数
class Pair[T,S](val first:T,val second:S)
//泛型类
trait Pair[T]
//泛型特质
当类型被指定的时候构成具体的类、函数等
val getInt = getType[Int] _
支持类型推断
val p1 = new Pair[25,25.0]
//生成Pair[Int,Double]类
类型参数界限,型变(协变与逆变)
高级特性之并发:
注解是在编译和运行之外,对程序进行操作
Scala使用Actor作为其并发编程模型
一种基于消息传递而非资源共享的并发模型,能尽可能避免死锁和共享状态
class HI extends Actor
object HELLO extends Actor
示例:
import akka.actor.{ Actor, ActorSystem, Props }
object text2 extends App {
val hiscala = ActorSystem()
class HI extends Actor{
def act(){
while(true){
receive {
case msg: String => println(“HI” + msg)
}}
}
}
def SHOW (m:String) = {
val ACTORa = hiscala.actorof(Props[HI])
ACTORa ! m
ACTORa ! m+m
}
val scala = Array[String](“SCALA”,”ACTOR”,”AKKA”)
for(i <- scala) SHOW(i)
for(i <- scala) SHOW(i)
}
消息传递是Actor的核心
使用 ! 向actor发送消息
actor使用receive接收消息
msg代表actor当前接收到的消息
actor通过react实现线程的复用
def act() { react { .. } }
act方法只能获取一次线程
actor(Scala.Actor)的主体是act方法,不能被外界显式调用
Actor使用原则:避免共享、不调用方法、足够简单、异步调用、使用react、容错