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