Scala學(xué)習(xí)筆記:
1.1 scala的基礎(chǔ)語(yǔ)法
聲明與定義(賦值):聲明變量時(shí)可以指定類(lèi)型,不指定也可以自動(dòng)識(shí)別數(shù)值類(lèi)型
?Val常量val x = 10val x:Int=10
?Var變量
?可以一次聲明多個(gè)變量val x1,x2,x3 =10
?def聲明函數(shù)
?scala的注釋?zhuān)焊鷍ava中的相同,//行注釋/**/塊注釋
1.2數(shù)值類(lèi)型
支持4種數(shù)據(jù)類(lèi)型:
?整行值:Int、Long,Short,Double
?浮點(diǎn)型值:FloatDouble
?布爾型值:Boolean(truefalse)
?字符型值:CharString// char使用‘’String使用“”進(jìn)行區(qū)分(自動(dòng)識(shí)別)
操作符運(yùn)算:
?數(shù)學(xué)操作符:+ - * / %
?比較操作符:> < >= <=產(chǎn)生布爾值
?邏輯操作符:&&||產(chǎn)生布爾值
?對(duì)等操作符:==!=布爾值
?位操作符:& | ^ ~
通用規(guī)范:
?Scala基于行的語(yǔ)言,分號(hào)和換行均可作為語(yǔ)句的結(jié)束
?多行做為一個(gè)整體,使用{}創(chuàng)建符合表達(dá)式,大括號(hào)之間的語(yǔ)句不作為語(yǔ)句的結(jié)束
?盡量不要使用保留字
1.3 scala語(yǔ)言入門(mén)
1.3.1結(jié)構(gòu)
主要是學(xué)會(huì)scala程序塊中的結(jié)構(gòu)控制語(yǔ)句
(1)判斷(if表達(dá)式)
def max(x:Int,y:Int) = if(x>y) x else y//if可以作為返回值進(jìn)行復(fù)制
(2)循環(huán)(while..do)
val x=10
while(x>0){
if(x%2==0){
println(x)
}
x-=1
}
(3)枚舉(for枚舉):枚舉對(duì)象可以為范圍,也可以為數(shù)組、字符串等
使用指針指向:
for (x <- 1 to 10) println(x)
//還可以在for枚舉的條件中添加if判斷,
for( x<-1 to 10;if(x%2==0)) println(x)或for(x <- 1 to 10 if x%2==0) println(x)
//多層嵌套枚舉;同樣也可以添加篩選條件
for(x <- 1 to 10;y <- 1 to 5 )
println(x*y)
// for枚舉后的表達(dá)式可以作為結(jié)果返回:關(guān)鍵字yield
val v = for( x <- 1 to 10) yield x? //v = Vector[1,2,3 ….,10]
(4)匹配(match表達(dá)式):類(lèi)似于java中的case when
a? match{
e1 => E1
case? e2 => E2
}
(5)異常處理(throw、try)類(lèi)似于java
(6)輸出(print、println)
類(lèi)似于java的console輸出
(7)輸入(readLine、readInt)
用于從控制臺(tái),接收輸入的數(shù)值
Var name = readLine(“please input your
name:”)
Scala程序中,最后一行返回的數(shù)值,就是return的結(jié)果,所以無(wú)需單獨(dú)使用return語(yǔ)句
1.3.2數(shù)組
(1)數(shù)組的聲明;
Var arr = new Array[T](10)//初始化聲明數(shù)組的長(zhǎng)度,及類(lèi)型
Var arr = Array(123,234)//自動(dòng)識(shí)別創(chuàng)建的數(shù)組的
(2)數(shù)據(jù)的使用:
數(shù)組的下標(biāo)是從0開(kāi)始的,arr.length-1結(jié)束;超過(guò)會(huì)顯示數(shù)組下標(biāo)越界
獲取數(shù)據(jù)的值:arr(下標(biāo))eg:arr(0)
(3)可變數(shù)組
引入ArrayBuffer類(lèi):import? scala.collection.mutable.ArrayBuffer
?初始化ArrayBuffer
Valarr = ArrayBuffer[T]()
?增加元素
arr+=(1,2,3,4)
?增加一個(gè)數(shù)組
arr ++= Array(200,300)
?截掉最后的2個(gè)元素
arr.trimEnd(2)
?在第2個(gè)位置,插入元素元素100(可以插入多個(gè)元素,下標(biāo)從0開(kāi)始,插入位置不要超過(guò)數(shù)組的最長(zhǎng)下標(biāo))
arr.insert(2,100,200)
?移除下標(biāo)為3位置的元素
arr.remove(3)
?移除下標(biāo)為2位置開(kāi)始的,3個(gè)元素
arr.remove(2,3)
?可變數(shù)組轉(zhuǎn)換成不變數(shù)組
var arr1 = arr.toArray
?將不可變數(shù)組轉(zhuǎn)換成可變數(shù)組
Var arr2 = arr.toBuffer
?倒序遍歷
for(x <- arr2.reverse)
println(x)
?數(shù)組排序:引入import scala.util.Sorting
Var arr1 = Sorting.quickSort(arr)
//升序排序
?拼接數(shù)組為字符串,指定分割符
arr.mkString(“,”)// 1,2,3,4
1.3.3映射
類(lèi)似于java中的map集合
(1)映射的聲明:
?兩種方式;
Val map = Map(a1 ->
b1,a2->b2,a3->b3)
或者:val map =
Map((a1,b1),(a2,b2),(a3,b3))
(2)映射的使用;
?獲取對(duì)應(yīng)鍵的值
Var value = map(a1)或者var value =
map.get(a1)
?使用contains方法檢查映射中是否含有某個(gè)key,返回boolean
Var v = map.contains(a1)
?組合調(diào)用,getOrElse方法,
Var v = map.getOrElse(a1,0)#如果有key則返回value值,否則返回0
?更新或新增map值
map += (a4 -> b4)
?刪除鍵值對(duì)應(yīng)
map -= a4
?映射的枚舉
for((x,y) <- map)? println("key:"+x+"value:"+y)
?分別獲取鍵、值的集合
Var key = map.keySet
Var value = map.values
1.3.4元組
(1)元組是不同類(lèi)型值的集合,映射是二元的元組
var g = (1,1.2,'a',"mapeng")
g: (Int, Double, Char, String) = (1,1.2,a,mapeng)//自動(dòng)識(shí)別元組元素類(lèi)型
(2)元組的操作;
?利用_1 ,_2,_3訪(fǎng)問(wèn)元組的組元
Var v = g._1或者:var v = g _1(中間空格)
(3)利用zip方法把幾個(gè)集合結(jié)合起來(lái)
scala> var one = Array(123,456)
one: Array[Int] = Array(123, 456)
scala> var two
=Array("abc","fgh")
two: Array[String] = Array(abc, fgh)
scala> var three = one.zip(two)或者使用:var three = one
zip two
three: Array[(Int, String)] =? Array((123,abc), (456,fgh))//相當(dāng)于生成了一個(gè)二元數(shù)組
(4)利用zip結(jié)合數(shù)組,生成映射
對(duì)應(yīng)的生成一個(gè)以數(shù)組one為鍵,數(shù)組two為值的映射
scala> var four = one zip two toMap
scala.collection.immutable.Map[Int,String]
= Map(123 -> abc, 456 -> fgh)
1.3.5包和引用
1.4 scala面向?qū)ο?/p>
1.4.1類(lèi)(class)
Scala類(lèi)都是默認(rèn)(public)公有可見(jiàn)性的,且一個(gè)文件里可以包含有多個(gè)類(lèi),省略的權(quán)限控制申明為public ;在類(lèi)中申明的執(zhí)行體(方法除外),在初始化對(duì)象時(shí),都會(huì)被執(zhí)行
申明一個(gè)Person類(lèi)
classPerson1(name:String,varage:Int,valsex:Char) {
valscore:Int =100
//無(wú)參數(shù)的函數(shù)
defmyPrint=println("name"+name+"age:"+age+"sex"+sex)
println(“每次初始化對(duì)象時(shí),都會(huì)被執(zhí)行”)
}
?申明一個(gè)帶有主構(gòu)造器的類(lèi),包括的屬性有:name;age;sex,其中:內(nèi)部申明屬性score
如果申明類(lèi)時(shí),沒(méi)有提供主構(gòu)造器,則提供默認(rèn)構(gòu)造器(無(wú)參數(shù)),調(diào)用默認(rèn)構(gòu)造器或無(wú)參方法時(shí)省略方法后面的()
?Scala類(lèi),對(duì)應(yīng)屬性,都會(huì)默認(rèn)生成其對(duì)應(yīng)的getter setter方法
l共有字段,生成的是公有的getter setter方法
l私有字段,生成的是私有的getter setter方法
l對(duì)于主構(gòu)造器中的變量,其理解為:private val name:String故為私有的字段
?構(gòu)造實(shí)例對(duì)象val person = new Person(“zhangsan”,20,”m”)
可以調(diào)用:person.myPrint//無(wú)參的方法在調(diào)用時(shí),不能帶()
Person.ageperson.sexperson.score
1.4.2構(gòu)造器
1.4.1.1主構(gòu)造器
classPerson1(privatevalname:String,varage:Int =0,address:String="",privatevarschool:String=""){
vargrade:Int =if(age>7)age-7else0
println(" I'm in main
constructor. ")
definfo() =" name is
"+name+", age is "+age+", address is "+address
}
Scala類(lèi)有一個(gè)主構(gòu)造器和多個(gè)輔助構(gòu)造器,每個(gè)輔助器的名稱(chēng)為this,每個(gè)輔助構(gòu)造器都必須用已經(jīng)定義的主構(gòu)造器或者輔助構(gòu)造器開(kāi)始定義
?主構(gòu)造器
如果一個(gè)類(lèi)沒(méi)有顯示的定義主構(gòu)造器(主構(gòu)造器的參數(shù)放置在類(lèi)名之后),則有一個(gè)默認(rèn)的無(wú)參主構(gòu)造器
?對(duì)于主構(gòu)造器中var
val private等標(biāo)注的參數(shù),都會(huì)成為類(lèi)的對(duì)應(yīng)字段,并生成對(duì)應(yīng)的默認(rèn)settergetter方法
?對(duì)于未用var val
private等標(biāo)注的參數(shù),如果類(lèi)中的任何一個(gè)地方用到了該參數(shù),則該參數(shù)會(huì)轉(zhuǎn)換為類(lèi)的字段,否則不會(huì)
?主構(gòu)造器提供參數(shù)的默認(rèn)值設(shè)置
?主構(gòu)造器的函數(shù)體,是類(lèi)中除了方法定義以外的其他語(yǔ)句,執(zhí)行體在初始化對(duì)象時(shí)都會(huì)被執(zhí)行
?初始化對(duì)象,可以只初始化主函數(shù)的前幾個(gè)字段,eg:
Val person = new Person(“zhagnsan”,20)//可以通過(guò),只是主構(gòu)造器的其他參數(shù)為空
1.4.1.2輔助構(gòu)造器
輔助構(gòu)造器通過(guò)this來(lái)定義,且必須先使用主構(gòu)造器或者其他已定義的輔助構(gòu)造器;
注:輔助構(gòu)造器的的參數(shù)前不能再添加val var標(biāo)識(shí),否則會(huì)報(bào)錯(cuò)
classPerson1(valname:String){
varage:Int =0
varaddr:String=""
println("主構(gòu)造器")
//輔助構(gòu)造器
defthis(name:String,age:Int){
this(name)
this.age=age
println("輔助構(gòu)造1")
}
}
1.4.3對(duì)象(object)
Object用來(lái)定義某個(gè)類(lèi)的單個(gè)實(shí)例
Scala中沒(méi)有靜態(tài)方法和靜態(tài)字段,但是可以使用object語(yǔ)法來(lái)實(shí)現(xiàn)類(lèi)似的功能。使用object中的常量和方法,通過(guò)類(lèi)名直接調(diào)用,不用實(shí)例化;
Object的構(gòu)造器不接受參數(shù)傳遞
1.4.3.1伴生類(lèi)和伴生對(duì)象
單例對(duì)象與類(lèi)同名時(shí),這個(gè)單例對(duì)象就成為這個(gè)類(lèi)的伴生對(duì)象,而這個(gè)類(lèi)也成為這個(gè)單例對(duì)象的伴生類(lèi);伴生類(lèi)和伴生對(duì)象要在同一個(gè)源文件中定義,伴生類(lèi)可以訪(fǎng)問(wèn)伴生對(duì)象的私有成員,必須通過(guò)伴生對(duì)象.字段(方法)來(lái)訪(fǎng)問(wèn)
classPerson(valname:String) {
privatevalage=100
defadd(x:Int,y:Int) =x+y
defmyPrint=println("name:"+name+"sex:"+Person.sex)
}
objectPerson{
privatevalsex:Char ='m'
}
1.4.3.2 apply介紹
伴生對(duì)象實(shí)例化伴生類(lèi)的方法
;
在伴生對(duì)象中,定義apply方法,當(dāng)調(diào)用Object(obj1,obj2…)方法時(shí),實(shí)際是調(diào)用了伴生對(duì)象的apply方法,對(duì)伴生類(lèi)對(duì)象進(jìn)行了實(shí)例化
classPerson(valname:String) {
privatevalage=100
defadd(x:Int,y:Int) =x+y
defmyPrint=println("name:"+name+"sex:"+Person.sex)
}
objectPerson{
privatevalsex:Char ='m'
//定義apply方法,實(shí)例化伴生對(duì)象
defapply(name:String) =newPerson(name) //實(shí)際是通過(guò)apply方法進(jìn)行了對(duì)象實(shí)例化,避免了手動(dòng)new對(duì)象
}
1.4.4繼承
Any是整個(gè)scala繼承的根,所有類(lèi)都是直接或者間接的繼承了Any;
extends是scala中實(shí)現(xiàn)繼承的保留字,
?子類(lèi)在繼承超類(lèi)時(shí),必須把父類(lèi)的主構(gòu)造器的所有參數(shù)都填滿(mǎn)
class Worker(name:String,age:Int,val salary:Long)extends? Person1(name,age)
?子類(lèi)繼承超類(lèi)所有的非私有成員;
?子類(lèi)構(gòu)造器運(yùn)行在超類(lèi)構(gòu)造器之后;
?子類(lèi)重寫(xiě)超類(lèi)的成員(具有相同的名稱(chēng)和參數(shù)),使用override保留字進(jìn)行方法、字段的重寫(xiě)
?如果類(lèi)被聲明為final類(lèi),則為終極類(lèi),不能被子類(lèi)繼承。聲明為final的字段或者方法,不能被子類(lèi)重寫(xiě)
?在子類(lèi)中調(diào)用超類(lèi)的方法,使用super.
?單例對(duì)象也能被繼承
?子類(lèi)的重寫(xiě)、修改會(huì)檢查超類(lèi),但是,超類(lèi)的修改并不會(huì)檢查其子類(lèi)
?重寫(xiě):子類(lèi)中,def只能重寫(xiě)超類(lèi)的def,
val能重寫(xiě)超類(lèi)的val或不帶參數(shù)的def,var只能重寫(xiě)超類(lèi)中抽象的var或者超類(lèi)中的getter/setter對(duì)
1.4.4.1類(lèi)型檢查和轉(zhuǎn)換
?類(lèi)型檢查:isInstanceOf[T]
person.isInstanceOf[Person]//檢查person是不是Person類(lèi)的一個(gè)實(shí)例
?獲取對(duì)象類(lèi)型
person.getClass或者:classOf[Person]
1.4.4.2保護(hù)(protected)
?當(dāng)一個(gè)類(lèi)不想被繼承或者重寫(xiě)時(shí),可以在該類(lèi)定義時(shí)加上final關(guān)鍵字,代表終極類(lèi)
?當(dāng)一個(gè)類(lèi)的某個(gè)方法或者字段不想被重寫(xiě)時(shí),可以加上final關(guān)鍵字
?當(dāng)超類(lèi)中的某些成員需要被子類(lèi)繼承,又不想對(duì)以外成員可見(jiàn)時(shí),可以在成員聲明前加上protected關(guān)鍵字
?類(lèi)中protected的成員對(duì)其子類(lèi)可見(jiàn),但對(duì)其超類(lèi)不可見(jiàn)
1.4.4.3抽象
只要類(lèi)中有任意一個(gè)為抽象成員,那么該類(lèi)就必須用abstract標(biāo)記;(抽象字段,是指在類(lèi)中沒(méi)有被初始化賦值、抽象方法,是指方法沒(méi)有具體的方法實(shí)現(xiàn)體)
抽象類(lèi)不能被實(shí)例化
重寫(xiě)抽象方法、抽象字段不需要使用override關(guān)鍵字
1.4.5特質(zhì)(trait)
特質(zhì)是scala里代碼復(fù)用的基礎(chǔ)單元,封裝了方法和字段的定義;其定義與普通類(lèi)相似,除了不能擁有構(gòu)造參數(shù);相似于java中的接口,但是特質(zhì)支持部分實(shí)現(xiàn),并不全是抽象
trait reset {
def reset (m : Int, n : Int) = if (m >= n) 1;
}
特質(zhì)的成員可以是抽象的,并且不需要使用abstract關(guān)鍵字聲明;
同樣,重寫(xiě)特質(zhì)的抽象方法,不用加上abstract關(guān)鍵字
?一旦特質(zhì)被定義了,就可以混入到類(lèi)中
class?week?extends?reset?{......}
?當(dāng)要混入多個(gè)特質(zhì)時(shí),利用with保留字,可以實(shí)現(xiàn)多繼承
class?week?extends?reset?with?B?with?C?{......}
特質(zhì)的構(gòu)造是有順序的:從左到右被構(gòu)造
u超類(lèi)
u父特質(zhì)
u第一個(gè)特質(zhì)
u第二個(gè)特質(zhì)(父特質(zhì)不重復(fù)構(gòu)造
u類(lèi)
1.5高階函數(shù)
函數(shù)是scala的編程的“一等公民”,函數(shù)值可以自由的被存儲(chǔ)和傳遞
1.5.1匿名函數(shù)
沒(méi)有函數(shù)名
(x:Int) => x*x
有名函數(shù):