[大資料]Scala 速學手冊2
Scala 速學手冊2
1 類、物件、繼承、特質
1.1 類
1 類的定義
//在Scala中,類並不用宣告為public。 //Scala原始檔中可以包含多個類,所有這些類都具有公有可見性。 class Person { //用val修飾的變數是隻讀屬性,有getter但沒有setter //(相當與Java中用final修飾的變數) val id = "9527" //用var修飾的變數既有getter又有setter var age: Int = 18 //類私有欄位,只能在類的內部使用 private var name: String = "唐伯虎" //物件私有欄位,訪問許可權更加嚴格的,Person類的方法只能訪問到當前物件的欄位 private[this] val pet = "小強" }
2 類的構造器
注意:主構造器會執行類定義中的所有語句
/** *每個類都有主構造器,主構造器的引數直接放置類名後面,與類交織在一起 */ class Student(val name: String, val age: Int){ //主構造器會執行類定義中的所有語句 println("執行主構造器") try { println("讀取檔案") throw new IOException("io exception") } catch { case e: NullPointerException => println("列印異常Exception : " + e) case e: IOException => println("列印異常Exception : " + e) } finally { println("執行finally部分") } private var gender = "male" //用this關鍵字定義輔助構造器 def this(name: String, age: Int, gender: String){ //每個輔助構造器必須以主構造器或其他的輔助構造器的呼叫開始 this(name, age) println("執行輔助構造器") this.gender = gender } } /** *構造器引數可以不帶val或var,如果不帶val或var的引數至少被一個方法所使用, *那麼它將會被提升為欄位 */ //在類名後面加private就變成了私有的 class Queen private(val name: String, prop: Array[String], private var age: Int = 18){ println(prop.size) //prop被下面的方法使用後,prop就變成了不可變得物件私有欄位,等同於private[this] val prop //如果沒有被方法使用該引數將不被儲存為欄位,僅僅是一個可以被主構造器中的程式碼訪問的普通引數 def description = name + " is " + age + " years old with " + prop.toBuffer } object Queen{ def main(args: Array[String]) { //私有的構造器,只有在其伴生物件中使用 val q = new Queen("hatano", Array("蠟燭", "皮鞭"), 20) println(q.description()) } }
1.2 物件
在Scala中沒有靜態方法和靜態欄位,但是可以使用object這個語法結構來達到同樣的目的
- 存放工具方法和常量
- 高效共享單個不可變的例項
- 單例模式
import scala.collection.mutable.ArrayBuffer object SingletonDemo { def main(args: Array[String]) { //單例物件,不需要new,用【類名.方法】呼叫物件中的方法 val session = SessionFactory.getSession() println(session) } } object SessionFactory{ //該部分相當於java中的靜態塊 var counts = 5 val sessions = new ArrayBuffer[Session]() while(counts > 0){ sessions += new Session counts -= 1 } //在object中的方法相當於java中的靜態方法 def getSession(): Session ={ sessions.remove(0) } } class Session{ }
2 伴生物件
在Scala的類中,與類名相同的物件叫做伴生物件,類和伴生物件之間可以相互訪問私有的方法和屬性
class Dog {
val id = 1
private var name = "herry"
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()
}
}
3 apply方法
通常我們會在類的伴生物件中定義apply方法,當遇到類名(引數1,…引數n)時apply方法會被呼叫
object ApplyDemo {
def main(args: Array[String]) {
//呼叫了Array伴生物件的apply方法
//def apply(x: Int, xs: Int*): Array[Int]
//arr1中只有一個元素5
val arr1 = Array(5)
println(arr1.toBuffer)
//new了一個長度為5的array,數組裡麵包含5個null
var arr2 = new Array(5)
}
}
4 應用程式物件
Scala程式都必須從一個物件的main方法開始,可以通過擴充套件App特質,不寫main方法。
object AppObjectDemo extends App{
//不用寫main方法
println("I love you Scala")
}
1.2 繼承
1 擴充套件類
在Scala種擴充套件類的方法和Java一樣都是使用extends 關鍵字
2 重寫方法
在Scala種重寫一個非抽象的方法必須使用override修飾符
3 型別檢查和轉換
scala | java |
---|---|
obj.isInstanceOf[C] | obj instanceof C |
obj.asInstanceOf[C] | ©obj |
classOf[C] | C.class |
超類的構造
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關鍵字,寫了也可以
def run(): Int = {
1
}
}
2 模式匹配和樣例類
Scala有一個十分強大的模式匹配機制,可以應用到很多場合:如switch語句、型別檢查等。並且Scala還提供了樣例類,對模式匹配進行了優化,可以快速進行匹配
2.1 匹配字串
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("真不知道你們在說什麼...")
}
}
2.2 匹配型別
注意:case y: Double if(y >= 0) => …
模式匹配的時候還可以新增守衛條件。如不符合守衛條件,將掉入case _中
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")
}
}
2.3 匹配陣列、元組
注意: 在Scala中列表要麼為空(Nil表示空列表)要麼是一個head元素加上一個tail列表。
9 :: List(5, 2) :: 操作符是將給定的頭和尾建立一個新的列表
注意: :: 操作符是右結合的,如9 :: 5 :: 2 :: Nil相當於 9 :: (5 :: (2 :: Nil))
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")
}
}
2.4 樣例類
在Scala中樣例類是一中特殊的類,可用於模式匹配。case class是多例的,後面要跟構造引數,case object是單例的
import scala.util.Random
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")
}
}
}
2.5 Option型別
在Scala中Option型別樣例類用來表示可能存在或也可能不存在的值(Option的子類有Some和None)。Some包裝了某個值,None表示沒有值
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)
}
}
2.6 偏函式
被包在花括號內沒有match的一組case語句是一個偏函式,它是PartialFunction[A, B]的一個例項,A代表引數型別,B代表返回型別,常用作輸入模式匹配
object PartialFuncDemo {
def func1: PartialFunction[String, Int] = {
case "one" => 1
case "two" => 2
case _ => -1
}
def func2(num: String) : Int = num match {
case "one" => 1
case "two" => 2
case _ => -1
}
def main(args: Array[String]) {
println(func1("one"))
println(func2("one"))
}
}