1.1. 什么是Scala
Scala是一種多范式的編程語言褥赊,其設(shè)計的初衷是要集成面向?qū)ο缶幊毯秃瘮?shù)式編程的各種特性登馒。Scala運(yùn)行于Java平臺(Java虛擬機(jī))式曲,并兼容現(xiàn)有的Java程序。[圖片上傳失敗...(image-c23538-1527488548129)]
1.2. 為什么要學(xué)Scala
1.優(yōu)雅:這是框架設(shè)計師第一個要考慮的問題发笔,框架的用戶是應(yīng)用開發(fā)程序員盟萨,API是否優(yōu)雅直接影響用戶體驗(yàn)。
2.速度快:Scala語言表達(dá)能力強(qiáng)了讨,一行代碼抵得上Java多行捻激,開發(fā)速度快;Scala是靜態(tài)編譯的前计,所以和JRuby,Groovy比起來速度會快很多胞谭。
- 能融合到Hadoop生態(tài)圈:Hadoop現(xiàn)在是大數(shù)據(jù)事實(shí)標(biāo)準(zhǔn),Spark并不是要取代Hadoop男杈,而是要完善Hadoop生態(tài)丈屹。JVM語言大部分可能會想到Java,但Java做出來的API太丑伶棒,或者想實(shí)現(xiàn)一個優(yōu)雅的API太費(fèi)勁旺垒。
[圖片上傳失敗...(image-b141d4-1527488548129)]
2. Scala編譯器安裝
2.1. 安裝JDK
因?yàn)镾cala是運(yùn)行在JVM平臺上的,所以安裝Scala之前要安裝JDK
2.2. 安裝Scala
2.2.1. Windows安裝Scala編譯器
訪問Scala官網(wǎng)http://www.scala-lang.org/下載Scala編譯器安裝包肤无,目前最新版本是2.12.x先蒋,但是目前大多數(shù)的框架都是用2.10.x編寫開發(fā)的,所以這里推薦2.10.x版本宛渐,下載scala-2.10.6.msi后點(diǎn)擊下一步就可以了
2.2.2. Linux安裝Scala編譯器
下載Scala地址http://downloads.typesafe.com/scala/2.10.6/scala-2.10.6.tgz然后解壓Scala到指定目錄
tar -zxvf scala-2.10.6.tgz -C /usr/java
配置環(huán)境變量竞漾,將scala加入到PATH中
vi /etc/profile
export JAVA_HOME=/usr/java/jdk1.7.0_45
export PATH=$PATH:$JAVA_HOME/bin:/usr/java/scala-2.10.6/bin
2.2.3. Scala開發(fā)工具安裝
目前Scala的開發(fā)工具主要有兩種:Eclipse和IDEA眯搭,這兩個開發(fā)工具都有相應(yīng)的Scala插件,如果使用Eclipse业岁,直接到Scala官網(wǎng)下載即可http://scala-ide.org/download/sdk.html坦仍。
由于IDEA的Scala插件更優(yōu)秀,大多數(shù)Scala程序員都選擇IDEA叨襟,可以到http://www.jetbrains.com/idea/download/下載社區(qū)免費(fèi)版,點(diǎn)擊下一步安裝即可幔荒,安裝時如果有網(wǎng)絡(luò)可以選擇在線安裝Scala插件糊闽。這里我們使用離線安裝Scala插件:
1.安裝IDEA,點(diǎn)擊下一步即可爹梁。由于我們離線安裝插件右犹,所以點(diǎn)擊Skip All and Set Defaul
2.下載IEDA的scala插件,地址http://plugins.jetbrains.com/?idea_ce
[圖片上傳失敗...(image-395c8d-1527488548129)]
3.安裝Scala插件:Configure -> Plugins -> Install plugin from disk -> 選擇Scala插件 -> OK -> 重啟IDEA
[圖片上傳失敗...(image-e87daf-1527488548129)]
[圖片上傳失敗...(image-fe195c-1527488548129)]
[圖片上傳失敗...(image-1dd0dd-1527488548129)]
[圖片上傳失敗...(image-b0367d-1527488548129)]
3. Scala基礎(chǔ)
3.1. 聲明變量
|
<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.scala /*
- Created by ZX on 2015/11/6.
/ object VariableDemo { def main(args: Array[String]) { //使用val定義的變量值是不可變的姚垃,相當(dāng)于java里用final修飾的變量 val i = 1 //使用var定義的變量是可變得念链,在Scala中鼓勵使用val var s = "hello" //Scala編譯器會自動推斷變量的類型,必要的時候可以指定類型</pre>
<pre style="mso-pagination:widow-orphan;background:white"> //變量名在前积糯,類型在后 val str: String = "itcast" }
}</pre>
|
3.2. 常用類型
Scala和Java一樣掂墓,有7種數(shù)值類型Byte、Char看成、Short君编、Int、Long川慌、Float和Double(無包裝類型)和一個Boolean類型
3.3. 條件表達(dá)式
Scala的的條件表達(dá)式比較簡潔吃嘿,例如:
|
<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.scala /*
- Created by ZX on 2015/11/7.
/ object ConditionDemo { def main(args: Array[String]) { val x = 1 //判斷x的值,將結(jié)果賦給y val y = if (x > 0) 1 else -1 //打印y的值 println(y) //支持混合類型表達(dá)式 val z = if (x > 1) 1 else "error" //打印z的值 println(z) //如果缺失else梦重,相當(dāng)于if (x > 2) 1 else () val m = if (x > 2) 1 println(m) //在scala中每個表達(dá)式都有值兑燥,scala中有個Unit類,寫做(),相當(dāng)于Java中的void val n = if (x > 2) 1 else ()
println(n) //if和else if val k = if (x < 0) 0 else if (x >= 1) 1 else -1 println(k)
}
}</pre>
|
3.4. 塊表達(dá)式
|
<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.scala /*
- Created by ZX on 2015/11/7.
/ object BlockExpressionDemo { def main(args: Array[String]) { val x = 0 //在scala中{}中課包含一系列表達(dá)式琴拧,塊中最后一個表達(dá)式的值就是塊的值 //下面就是一個塊表達(dá)式 val result = { if (x < 0){
-1 } else if(x >= 1) { 1 } else { "error" }
} //result的值就是塊表達(dá)式的結(jié)果 println(result)
}
}</pre>
|
3.5. 循環(huán)
在scala中有for循環(huán)和while循環(huán)降瞳,用for循環(huán)比較多
<pre style="mso-pagination:widow-orphan;background:white">for循環(huán)語法結(jié)構(gòu):for (i <- 表達(dá)式/數(shù)組/集合)</pre>
|
<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.scala /*
- Created by ZX on 2015/11/7.
/ object ForDemo { def main(args: Array[String]) { //for(i <- 表達(dá)式),表達(dá)式1 to 10返回一個Range(區(qū)間)</pre>
<pre style="mso-pagination:widow-orphan;background:white"> //每次循環(huán)將區(qū)間中的一個值賦給i for (i <- 1 to 10)
println(i) //for(i <- 數(shù)組) val arr = Array("a", "b", "c") for (i <- arr)
println(i) //高級for循環(huán) //每個生成器都可以帶一個條件,注意:if前面沒有分號 for(i <- 1 to 3; j <- 1 to 3 if i != j)
print((10 * i + j) + " ")
println() //for推導(dǎo)式:如果for循環(huán)的循環(huán)體以yield開始蚓胸,則該循環(huán)會構(gòu)建出一個集合</pre>
<pre style="mso-pagination:widow-orphan;background:white"> //每次迭代生成集合中的一個值 val v = for (i <- 1 to 10) yield i * 10 println(v)
}
}</pre>
|
3.6. 調(diào)用方法和函數(shù)
Scala中的+ - * / %等操作符的作用與Java一樣力崇,位操作符 & | ^ >> <<也一樣。只是有
一點(diǎn)特別的:這些操作符實(shí)際上是方法赢织。例如:
a + b
是如下方法調(diào)用的簡寫:
a.+(b)
a 方法 b可以寫成 a.方法(b)
3.7. 定義方法和函數(shù)
3.7.1. 定義方法
[圖片上傳失敗...(image-a6b603-1527488548129)]
方法的返回值類型可以不寫亮靴,編譯器可以自動推斷出來,但是對于遞歸函數(shù)于置,必須指定返回類型
3.7.2. 定義函數(shù)
[圖片上傳失敗...(image-c00ef5-1527488548129)]
3.7.3. 方法和函數(shù)的區(qū)別
在函數(shù)式編程語言中茧吊,函數(shù)是“頭等公民”贞岭,它可以像任何其他數(shù)據(jù)類型一樣被傳遞和操作
案例:首先定義一個方法,再定義一個函數(shù)搓侄,然后將函數(shù)傳遞到方法里面
[圖片上傳失敗...(image-d79b3a-1527488548129)]
|
<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.scala /*
- Created by ZX on 2015/11/11.
/ object MethodAndFunctionDemo { //定義一個方法 //方法m2參數(shù)要求是一個函數(shù)瞄桨,函數(shù)的參數(shù)必須是兩個Int類型</pre>
<pre style="mso-pagination:widow-orphan;background:white"> //返回值類型也是Int類型 def m1(f: (Int, Int) => Int) : Int = {
f(2, 6)
} //定義一個函數(shù)f1,參數(shù)是兩個Int類型讶踪,返回值是一個Int類型 val f1 = (x: Int, y: Int) => x + y //再定義一個函數(shù)f2 val f2 = (m: Int, n: Int) => m * n //main方法 def main(args: Array[String]) { //調(diào)用m1方法芯侥,并傳入f1函數(shù) val r1 = m1(f1)
println(r1) //調(diào)用m1方法,并傳入f2函數(shù) val r2 = m1(f2)
println(r2)
}
}</pre>
|
3.7.4. 將方法轉(zhuǎn)換成函數(shù)(神奇的下劃線)
[圖片上傳失敗...(image-ddfd28-1527488548129)]
4. 數(shù)組乳讥、映射柱查、元組、集合
4.1. 數(shù)組
4.1.1. 定長數(shù)組和變長數(shù)組
|
<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.scala import scala.collection.mutable.ArrayBuffer /*
- Created by ZX on 2015/11/11.
/ object ArrayDemo { def main(args: Array[String]) { //初始化一個長度為8的定長數(shù)組云石,其所有元素均為0 val arr1 = new ArrayInt //直接打印定長數(shù)組唉工,內(nèi)容為數(shù)組的hashcode值 println(arr1) //將數(shù)組轉(zhuǎn)換成數(shù)組緩沖汹忠,就可以看到原數(shù)組中的內(nèi)容了 //toBuffer會將數(shù)組轉(zhuǎn)換長數(shù)組緩沖 println(arr1.toBuffer) //注意:如果new淋硝,相當(dāng)于調(diào)用了數(shù)組的apply方法,直接為數(shù)組賦值 //初始化一個長度為1的定長數(shù)組 val arr2 = ArrayInt
println(arr2.toBuffer) //定義一個長度為3的定長數(shù)組 val arr3 = Array("hadoop", "storm", "spark") //使用()來訪問元素 println(arr3(2)) *//////////////////////////////////////////////////
//變長數(shù)組(數(shù)組緩沖) //如果想使用數(shù)組緩沖宽菜,需要導(dǎo)入import scala.collection.mutable.ArrayBuffer包val ab = ArrayBufferInt //向數(shù)組緩沖的尾部追加一個元素 //+=尾部追加元素* ab += 1 //追加多個元素 ab += (2, 3, 4, 5) //追加一個數(shù)組++= ab ++= Array(6, 7) //追加一個數(shù)組緩沖 ab ++= ArrayBuffer(8,9) //*打印數(shù)組緩沖ab
//在數(shù)組某個位置插入元素用insert* ab.insert(0, -1, 0) //刪除數(shù)組某個位置的元素用remove ab.remove(8, 2)
println(ab)
}
}</pre>
|
4.1.2. 遍歷數(shù)組
1.增強(qiáng)for循環(huán)
2.好用的until會生成腳標(biāo)谣膳,0 until 10 包含0不包含10
[圖片上傳失敗...(image-7d32da-1527488548119)]
|
<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.scala /*
- Created by ZX on 2015/11/12.
/ object ForArrayDemo { def main(args: Array[String]) { //初始化一個數(shù)組 val arr = Array(1,2,3,4,5,6,7,8) //增強(qiáng)for循環(huán) for(i <- arr)
println(i) //*好用的until會生成一個Range
//reverse是將前面生成的Range反轉(zhuǎn)* for(i <- (0 until arr.length).reverse)
println(arr(i))
}
}</pre>
|
4.1.3. 數(shù)組轉(zhuǎn)換
yield關(guān)鍵字將原始的數(shù)組進(jìn)行轉(zhuǎn)換會產(chǎn)生一個新的數(shù)組,原始的數(shù)組不變
[圖片上傳失敗...(image-6a6e95-1527488548119)]
|
<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.scala /*
- Created by ZX on 2015/11/12.
/ object ArrayYieldDemo { def main(args: Array[String]) { //定義一個數(shù)組 val arr = Array(1, 2, 3, 4, 5, 6, 7, 8, 9) //將偶數(shù)取出乘以10后再生成一個新的數(shù)組 val res = for (e <- arr if e % 2 == 0) yield e * 10 println(res.toBuffer) //更高級的寫法,用著更爽 //filter是過濾铅乡,接收一個返回值為boolean的函數(shù) //map相當(dāng)于將數(shù)組中的每一個元素取出來参歹,應(yīng)用傳進(jìn)去的函數(shù) val r = arr.filter(_ % 2 == 0).map(_ * 10)
println(r.toBuffer)
}
}</pre>
|
4.1.4. 數(shù)組常用算法
在Scala中,數(shù)組上的某些方法對數(shù)組進(jìn)行相應(yīng)的操作非常方便隆判!
[圖片上傳失敗...(image-6ebce7-1527488548119)]
4.2. 映射
在Scala中犬庇,把哈希表這種數(shù)據(jù)結(jié)構(gòu)叫做映射
4.2.1. 構(gòu)建映射
[圖片上傳失敗...(image-3ef147-1527488548119)]
4.2.2. 獲取和修改映射中的值
[圖片上傳失敗...(image-1ff9aa-1527488548119)]
好用的getOrElse
[圖片上傳失敗...(image-903ef4-1527488548119)]
注意:在Scala中,有兩種Map侨嘀,一個是immutable包下的Map臭挽,該Map中的內(nèi)容不可變;另一個是mutable包下的Map咬腕,該Map中的內(nèi)容可變
例子:
[圖片上傳失敗...(image-9de60c-1527488548119)]
注意:通常我們在創(chuàng)建一個集合是會用val這個關(guān)鍵字修飾一個變量(相當(dāng)于java中的final)欢峰,那么就意味著該變量的引用不可變,該引用中的內(nèi)容是不是可變涨共,取決于這個引用指向的集合的類型
4.3. 元組
映射是K/V對偶的集合纽帖,對偶是元組的最簡單形式,元組可以裝著多個不同類型的值举反。
4.3.1. 創(chuàng)建元組
[圖片上傳失敗...(image-fae745-1527488548119)]
4.3.2. 獲取元組中的值
[圖片上傳失敗...(image-535291-1527488548119)]
4.3.3. 將對偶的集合轉(zhuǎn)換成映射
[圖片上傳失敗...(image-fee793-1527488548119)]
4.3.4. 拉鏈操作
zip命令可以將多個值綁定在一起
[圖片上傳失敗...(image-e37f23-1527488548119)]
注意:如果兩個數(shù)組的元素個數(shù)不一致懊直,拉鏈操作后生成的數(shù)組的長度為較小的那個數(shù)組的元素個數(shù)
4.4. 集合
Scala的集合有三大類:序列Seq、集Set火鼻、映射Map室囊,所有的集合都擴(kuò)展自Iterable特質(zhì)
在Scala中集合有可變(mutable)和不可變(immutable)兩種類型雕崩,immutable類型的集合初始化后就不能改變了(注意與val修飾的變量進(jìn)行區(qū)別)
4.4.1. 序列
不可變的序列 import scala.collection.immutable._
在Scala中列表要么為空(Nil表示空列表)要么是一個head元素加上一個tail列表。
9 :: List(5, 2) :: 操作符是將給定的頭和尾創(chuàng)建一個新的列表
注意::: 操作符是右結(jié)合的融撞,如9 :: 5 :: 2 :: Nil相當(dāng)于 9 :: (5 :: (2 :: Nil))
|
<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.collect object ImmutListDemo { def main(args: Array[String]) { //創(chuàng)建一個不可變的集合 val lst1 = List(1,2,3) //將0插入到lst1的前面生成一個新的List val lst2 = 0 :: lst1 val lst3 = lst1.::(0) val lst4 = 0 +: lst1 val lst5 = lst1.+:(0) //將一個元素添加到lst1的后面產(chǎn)生一個新的集合 val lst6 = lst1 :+ 3 val lst0 = List(4,5,6) //將2個list合并成一個新的List val lst7 = lst1 ++ lst0 //將lst1插入到lst0前面生成一個新的集合 val lst8 = lst1 ++: lst0 //將lst0插入到lst1前面生成一個新的集合 val lst9 = lst1.:::(lst0)
println(lst9)
}
}</pre>
|
可變的序列 import scala.collection.mutable._
|
<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.collect import scala.collection.mutable.ListBuffer object MutListDemo extends App{ //構(gòu)建一個可變列表盼铁,初始有3個元素1,2,3 val lst0 = ListBufferInt //創(chuàng)建一個空的可變列表 val lst1 = new ListBuffer[Int] //向lst1中追加元素,注意:沒有生成新的集合 lst1 += 4 lst1.append(5) //將lst1中的元素最近到lst0中尝偎, 注意:沒有生成新的集合 lst0 ++= lst1 //將lst0和lst1合并成一個新的ListBuffer 注意:生成了一個集合 val lst2= lst0 ++ lst1 //將元素追加到lst0的后面生成一個新的集合 val lst3 = lst0 :+ 5 }</pre>
|
4.5. Set
不可變的Set
|
<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.collect import scala.collection.immutable.HashSet object ImmutSetDemo extends App{ val set1 = new HashSetInt //將元素和set1合并生成一個新的set饶火,原有set不變 val set2 = set1 + 4 //set中元素不能重復(fù) val set3 = set1 ++ Set(5, 6, 7) val set0 = Set(1,3,4) ++ set1 println(set0.getClass)
}</pre>
|
可變的Set
|
<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.collect import scala.collection.mutable object MutSetDemo extends App{ //創(chuàng)建一個可變的HashSet val set1 = new mutable.HashSetInt //向HashSet中添加元素 set1 += 2 //add等價于+= set1.add(4) set1 ++= Set(1,3,5)
println(set1) //刪除一個元素 set1 -= 5 set1.remove(2)
println(set1)
}</pre>
|
4.6. Map
|
<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.collect import scala.collection.mutable object MutMapDemo extends App{ val map1 = new mutable.HashMapString, Int //向map中添加數(shù)據(jù) map1("spark") = 1 map1 += (("hadoop", 2)) map1.put("storm", 3)
println(map1) //從map中移除元素 map1 -= "spark" map1.remove("hadoop")
println(map1)
}</pre>
|
5. 類、對象致扯、繼承肤寝、特質(zhì)
Scala的類與Java、C++的類比起來更簡潔急前,學(xué)完之后你會更愛Scala!F俟埂裆针!
5.1. 類
5.1.1. 類的定義
|
<pre style="mso-pagination:widow-orphan;background:white">//在Scala中,類并不用聲明為public寺晌。</pre>
<pre style="mso-pagination:widow-orphan;background:white">//Scala源文件中可以包含多個類世吨,所有這些類都具有公有可見性。 class Person { //用val修飾的變量是只讀屬性呻征,有g(shù)etter但沒有setter</pre>
<pre style="mso-pagination:widow-orphan;background:white"> //(相當(dāng)與Java中用final修飾的變量) val id = "9527" </pre>
<pre style="mso-pagination:widow-orphan;background:white">//用var修飾的變量既有g(shù)etter又有setter var age: Int = 18</pre>
<pre style="mso-pagination:widow-orphan;background:white">//類私有字段,只能在類的內(nèi)部使用private var name: String = "****唐伯虎" //對象私有字段,訪問權(quán)限更加嚴(yán)格的耘婚,Person類的方法只能訪問到當(dāng)前對象的字段 private[this] val pet = "****小強(qiáng)"</pre>
<pre style="mso-pagination:widow-orphan;background:white">}</pre>
|
5.1.2. 構(gòu)造器
注意:主構(gòu)造器會執(zhí)行類定義中的所有語句
|
<pre style="mso-pagination:widow-orphan;background:white">/*
每個類都有主構(gòu)造器,主構(gòu)造器的參數(shù)直接放置類名后面陆赋,與類交織在一起 / class Student(val* name: String, val age: Int){ //主構(gòu)造器會執(zhí)行類定義中的所有語句 println("****執(zhí)行主構(gòu)造器") try {
println("****讀取文件") throw new IOException("io exception")
} catch { case e: NullPointerException => println("****打印異常Exception : " + e) case e: IOException => println("****打印異常Exception : " + e)
} finally {
println("****執(zhí)行finally部分")
} private var gender = "male" //用this關(guān)鍵字定義輔助構(gòu)造器 def this(name: String, age: Int, gender: String){ //每個輔助構(gòu)造器必須以主構(gòu)造器或其他的輔助構(gòu)造器的調(diào)用開始</pre>
<pre style="mso-pagination:widow-orphan;background:white"> this(name, age)
println("****執(zhí)行輔助構(gòu)造器") this.gender = gender
}
}</pre>
|
|
<pre style="mso-pagination:widow-orphan;background:white">/*
**構(gòu)造器參數(shù)可以不帶val或var沐祷,如果不帶val或var的參數(shù)至少被一個方法所使用,</pre>
<pre style="mso-pagination:widow-orphan;background:white"> ****那么它將會被提升為字段 /</pre>
<pre style="mso-pagination:widow-orphan;background:white">//在類名后面加private就變成了私有的 class Queen private(val name: String, prop: Array[String], private var age: Int = 18){
println(prop.size) //prop*被下面的方法使用后攒岛,prop就變成了不可變得對象私有字段赖临,等同于private[this] val prop
//如果沒有被方法使用該參數(shù)將不被保存為字段,僅僅是一個可以被主構(gòu)造器中的代碼訪問的普通參數(shù)* def description = name + " is " + age + " years old with " + prop.toBuffer
} object Queen{ def main(args: Array[String]) {
//私有的構(gòu)造器灾锯,只有在其伴生對象中使用 val q = new Queen("hatano", Array("****蠟燭", "****皮鞭"), 20)
println(q.description())
}
}</pre>
|
5.2. 對象
5.2.1. 單例對象
在Scala中沒有靜態(tài)方法和靜態(tài)字段兢榨,但是可以使用object這個語法結(jié)構(gòu)來達(dá)到同樣的目的
1.存放工具方法和常量
2.高效共享單個不可變的實(shí)例
3.單例模式
|
<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.scala import scala.collection.mutable.ArrayBuffer /*
- Created by ZX on 2015/11/14.
/ object SingletonDemo { def main(args: Array[String]) { //單例對象,不需要new顺饮,用【類名.方法】調(diào)用對象中的方法 val session = SessionFactory.getSession() println(session)
}
} object SessionFactory{ //該部分相當(dāng)于java中的靜態(tài)塊 var counts = 5 val sessions = new ArrayBufferSession while(counts > 0){ sessions += new Session counts -= 1 } //在object中的方法相當(dāng)于java中的靜態(tài)方法 def getSession(): Session ={ sessions.remove(0)
}
} class Session{
}</pre>
|
5.2.2. 伴生對象
在Scala的類中吵聪,與類名相同的對象叫做伴生對象,類和伴生對象之間可以相互訪問私有的方法和屬性
|
<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.scala /*
- Created by ZX on 2015/11/14.
/ class Dog { val id = 1 private var name = "itcast" def printName(): Unit ={ //在Dog類中可以訪問伴生對象Dog的私有屬性 println(Dog.CONSTANT + name )
}
} /*
** 伴生對象 / object Dog { //伴生對象中的私有屬性* private val CONSTANT = "****汪汪汪 : " def main(args: Array[String]) { val p = new Dog //訪問私有的字段name p.name = "123" p.printName()
}
}</pre>
|
5.2.3. apply方法
通常我們會在類的伴生對象中定義apply方法兼雄,當(dāng)遇到類名(參數(shù)1,...參數(shù)n)時apply方法會被調(diào)用
|
<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.scala</pre>
<pre style="mso-pagination:widow-orphan;background:white"> /*
- Created by ZX on 2015/11/14.
/ object ApplyDemo { def main(args: Array[String]) { //調(diào)用了Array伴生對象的apply方法 //def apply(x: Int, xs: Int): Array[Int]
//arr1中只有一個元素5* val arr1 = Array(5)
println(arr1.toBuffer) //new了一個長度為5的array吟逝,數(shù)組里面包含5個null var arr2 = new Array(5)
}
}</pre>
|
5.2.4. 應(yīng)用程序?qū)ο?/h3>
Scala程序都必須從一個對象的main方法開始,可以通過擴(kuò)展App特質(zhì)赦肋,不寫main方法澎办。
|
<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.scala /*
- Created by ZX on 2015/11/14.
/ object AppObjectDemo extends App{ //不用寫main方法 println("I love you Scala")
}</pre>
|
5.3. 繼承
5.3.1. 擴(kuò)展類
在Scala中擴(kuò)展類的方式和Java一樣都是使用extends關(guān)鍵字
5.3.2. 重寫方法
在Scala中重寫一個非抽象的方法必須使用override修飾符
5.3.3. 類型檢查和轉(zhuǎn)換
|
Scala
|
Java
|
|
obj.isInstanceOf[C]
|
obj instanceof C
|
|
obj.asInstanceOf[C]
|
(C)obj
|
|
classOf[C]
|
C.class
|
5.3.4. 超類的構(gòu)造
|
<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.scala /*
- Created by ZX on 2015/11/10.
/ object ClazzDemo { def main(args: Array[String]) { *//val h = new Human
//println(h.fight)* }
} trait Flyable{ def fly(): Unit ={
println("I can fly")
} def fight(): String } abstract class Animal { def run(): Int val name: String } class Human extends Animal with Flyable{ val name = "abc" //打印幾次"ABC"? val t1,t2,(a, b, c) = {
println("ABC")
(1,2,3)
}
println(a)
println(t1._1) //在Scala中重寫一個非抽象方法必須用override修飾 override def fight(): String = { "fight with 棒子" } //在子類中重寫超類的抽象方法時嘲碱,不需要使用override關(guān)鍵字,寫了也可以 def run(): Int = { 1 }
}</pre>
|
6. 模式匹配和樣例類
Scala有一個十分強(qiáng)大的模式匹配機(jī)制局蚀,可以應(yīng)用到很多場合:如switch語句麦锯、類型檢查等。
并且Scala還提供了樣例類琅绅,對模式匹配進(jìn)行了優(yōu)化扶欣,可以快速進(jìn)行匹配
6.1. 匹配字符串
|
<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.cases import scala.util.Random object CaseDemo01 extends App{ val arr = Array("YoshizawaAkiho", "YuiHatano", "AoiSola") val name = arr(Random.nextInt(arr.length)) name match { case "YoshizawaAkiho" => println("****吉澤老師...") case "YuiHatano" => println("****波多老師...") case _ => println("****真不知道你們在說什么...")
}
}</pre>
|
6.2. 匹配類型
|
<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.cases import scala.util.Random object CaseDemo01 extends App{ //val v = if(x >= 5) 1 else if(x < 2) 2.0 else "hello" val arr = Array("hello", 1, 2.0, CaseDemo) val v = arr(Random.nextInt(4))
println(v) v match { case x: Int => println("Int " + x) case y: Double if(y >= 0) => println("Double "+ y) case z: String => println("String " + z) case _ => throw new Exception("not match exception")
}
}</pre>
|
注意****:case y: Double if(y >= 0) => ...
模式匹配的時候還可以添加守衛(wèi)條件。如不符合守衛(wèi)條件千扶,將掉入case _中
6.3. 匹配數(shù)組料祠、元組
|
<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.cases object CaseDemo03 extends App{ val arr = Array(1, 3, 5) arr match { case Array(1, x, y) => println(x + " " + y) case Array(0) => println("only 0") case Array(0, _) => println("0 ...") case _ => println("something else"*)
} val lst = List(3, -1) lst match { case 0 :: Nil => println("only 0") case x :: y :: Nil => println(s"x: $x y: $y") case 0 :: tail => println("0 ...") case _ => println("something else")
} val tup = (2, 3, 7) tup match { case (1, x, y) => println(s"1, $x , $y") case (_, z, 5) => println(z) case _ => println("else")
}
}</pre>
|
注意:在Scala中列表要么為空(Nil表示空列表)要么是一個head元素加上一個tail列表。
9 :: List(5, 2) :: 操作符是將給定的頭和尾創(chuàng)建一個新的列表
注意::: 操作符是右結(jié)合的澎羞,如9 :: 5 :: 2 :: Nil相當(dāng)于 9 :: (5 :: (2 :: Nil))
6.4. 樣例類
在Scala中樣例類是一中特殊的類髓绽,可用于模式匹配。case class是多例的妆绞,后面要跟構(gòu)造參數(shù)顺呕,case object是單例的
|
<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.cases import scala.util.Random</pre>
<pre style="mso-pagination:widow-orphan;background:white">case class SubmitTask(id: String, name: String) case class HeartBeat(time: Long) case object CheckTimeOutTask object CaseDemo04 extends App{ val arr = Array(CheckTimeOutTask, HeartBeat(12333), SubmitTask("0001", "task-0001")) arr(Random.nextInt(arr.length)) match { case SubmitTask(id, name) => { println(s"$id, $name")//前面需要加上s, $id直接取id的值 } case HeartBeat(time) => {
println(time)
} case CheckTimeOutTask => {
println("check")
}
}
}</pre>
|
6.5. Option類型
在Scala中Option類型樣例類用來表示可能存在或也可能不存在的值(Option的子類有Some和None)。Some包裝了某個值括饶,None表示沒有值
|
<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.cases object OptionDemo { def main(args: Array[String]) { val map = Map("a" -> 1, "b" -> 2) val v = map.get("b") match { case Some(i) => i case None => 0 }
println(v) //更好的方式 val v1 = map.getOrElse("c", 0)
println(v1)
}
}</pre>
|
6.6. 偏函數(shù)
被包在花括號內(nèi)沒有match的一組case語句是一個偏函數(shù)株茶,它是PartialFunction[A, B]的一個實(shí)例,A代表參數(shù)類型图焰,B代表返回類型启盛,常用作輸入模式匹配
|
<pre style="mso-pagination:widow-orphan;background:white">package cn.itcast.cases object PartialFuncDemo { def func1: PartialFunction[String, Int] = { case "one" => 1 case "two" => 2 case _ => -1 }</pre>
<pre style="mso-pagination:widow-orphan;background:white"> def func2(num: String) : Int = num match { case "one" => 1 case "two" => 2 case _ => -1 }</pre>
<pre style="mso-pagination:widow-orphan;background:white"> def main(args: Array[String]) {
println(func1("one"))
println(func2("one"))
} }</pre>
|