一、什麼是scala
scala 是基于JVMde 程式設計語言。JAVA是運作在jvm上的程式設計語言,java 源代碼通過jvm被編譯成class 檔案,然後在os上運作class 檔案。scala是運作在jvm 上的程式設計語言,scala源代碼通過jvm被編譯成class檔案,然後在os上運作class檔案。
二文法:
1.聲明值和變量
var a =12 // 定義變量 vary
val b = 23// 定義常量:value
2.有趣的文法特性
在scala的變量聲明時,可以不指定類型,由解釋器自己判斷。
“superman ”*3 //表示字元串“ superman”反複輸出3次
“superman ”*3 //實際上是字元串“ superman”調用方法*,傳入的參數是3
3.函數:
函數在聲明後,無論是否有“=”,都有傳回值。當沒有“=”的時候,表示傳回值是Unit類型,Unit類型的值是()。當有“=”的時候,傳回值是函數體中的最後一行的值。如果傳回值類型強制指定為Unit類型,那麼傳回值必定是()。
4. 判斷:
/** * 判斷if */ object Test21 extends App{ def judge(a:Int) :Int = { if(a > 0){ 1 //return相當于函數版的break語句 }else if(a < 0){ -1 }else{ 0 } } var c = judge(-3) println(c) }
5.循環
/** * while 和 for循環 */ object Test22 extends App{ /*while循環*/ // while(true){ // println("hello") // } /*for循環 scala中的for基本形态*/ // for(int i = 0 ; i < 5 ; i++) //java的for循環 // for( i : List) //增強for // println(1 to 10) //Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) // for(i <- 1 to 10 ){ //閉區間 // println(i) // } // for(i <- 1 until 10 ){ //開區間 // println(i) // } // for(i <- 1 until 10 reverse){ //倒序 不能使用 10 to 1 // println(i) // } /*進階for循環*/ //守衛 // for(i <- 1 to 10 reverse ; if i % 3 == 0){ // println(i) // } // for(i <- 1 to (10,3)){ //改變步長 // println(i) // } // for(i <- 1 to 10 ; j <- 1 to 5){ //雙重for循環 // println(i + " - " + j) // } // //for的推導式 // var c = for( i <- 1 to 10 )yield (i * 2) // println(c)
6.常用的資料結構
6.1數組
/** * 數組 */ object Test31 extends App{ /*定長數組*/ //使用new定義數組 // var arr1 = new Array[Int](5) // arr1(1) = 2 //// println(arr1) // for(i <- arr1){ // println(i) // } //使用Array類進行定義 var arr2 = Array(1,2,3,4,"hehe") // for( i <- arr2){ // println(i) // } // println(arr2.min) // println(arr2.max) // println(arr2.sum) // println(arr2.mkString("[",",","]")) //Arrays.toString(arr) [1,2,3] /*變長數組*/ // var arrbuf1 = ArrayBuffer(1,2,3,4) // arrbuf1 += 5 // arrbuf1 -= 3 // arrbuf1 ++= Array(3,4,5) // arrbuf1 --= Array(3,4,5) // arrbuf1.toArray // println(arrbuf1.mkString(",")) // var arrB = arr2.toBuffer // arrB += 9 // println(arrB.mkString(",")) //filter 和 map用法 var arr4 = Array(1,2,3,4,5) var arr5 = arr4.filter( _ % 2 == 0 ).map( _ * 2) println(arr5.mkString(",")) }
6.2映射
** * 映射 */ object Test32 extends App{ /*不可變的映射*/ //(zhangsan,18)鍵值對稱作對偶 用()表示 var map1 = Map[String,Int](("zhangsan" , 18) ,( "lisi" , 19)) map1 += ("wangwu" -> 80) // map1("zhangsan") = 12 map1 += ("zhangsan" -> 20) // println(map1("zhangsan")) // for(i <- map1){ // println(i) // } // if(map1.contains("zhaoliu")) // println(map1("zhaoliu")) /*可變的映射*/ // var mapB = scala.collection.mutable.Map[String,Int]("zhangsan"->20,"lisi"->12) // mapB("zhangsan") = 30 // for(i <- mapB){ // println(i) // } /*與java的互操作*/ // var list = new ArrayList[Int] // list.add(1) // list.add(2) // // for(i <- 0 to list.size() - 1 ){ // println(list.get(i)) // } /*map其他周遊方式*/ // for((k,v) <- map1){ //方式一 // println(k + "->" + v) // } //方式二 var set1 = map1.keys var set2 = map1.keySet for(i <- set1){ println(map1(i)) } // println(set2)
6.3元祖
/** * 元組 */ object Test33 extends App{ //元組定義 //對偶(使用“()”表示)隻是元組最簡單的形式 使用()表示 var t = (1,2,3,4) // for(i <- t){ //元組不能使用for周遊 // println(i) // } // println(t _3) //元組的下标從1開始 // println(t _1) //元組的下标從1開始 var (first,second,third,forth) = t // var (first,second,third,_) = t // println(second) var s = "Hello World!" // println(s.partition(_.isUpper)) //拉鍊操作 var arr1 = Array(1,2,3,4,5,6) var arr2 = Array("a","b","c","d","e") var arr3 = arr1.zip(arr2) // // for(i <- arr3){ // println(i) // } println(arr3.mkString(",")) var map = arr3.toMap //map for(i <- map){ println(i) }
7.類
類的定義 :使用class定義
類的字段:在類中使用var,val定義字段
類的方法:scala中,使用var定義字段預設提供setter和geter方法,對應的名稱為value_= 和value.
/** * 類的基本内容 */ class TestClass41{ // @BeanProperty var monary = 100 var monary = 100 // def show { // println("hello") // } } object Test41 extends App{ var a = new TestClass41() //執行個體化一個類 a.monary = 200 println(a.monary) // println(a.show) //scala使用var定義字段 預設生成對應的setter和getter方法 對應的名稱monary_= 和 monary // a setMonary 300 // println(a getMonary) //使用val定義字段的時候 scala不在提供setter方法 //@BeanProperty和private不能同時共用 }
/** * 類的基本内容2 */ class TestClass42{ private var monary = 0 def setMonary(a:Int){ //自定義setter方法 if(a > 0) this.monary = a } def getMonary = { //自定義getter方法 this.monary } } object Test42 extends App{ var c = new TestClass42 c setMonary -1000 println(c getMonary) }
構造器:
/** * 類的構造器 */ //class TestClass43(var name:String = "xxx" , var age:Int = 0) { //主構造器 帶參數稱為預設值 // //// var name:String //需要初始化 //// var age:Int //// public TestClass43 {} //java的構造器寫法 // println("name=" + name) // println("age=" + age) // //} class TestClass43 { //輔助構造器 var name:String = "lisi" //需要初始化 var age:Int = 0 def this(name:String ){ this() //輔助構造器第一行要調用主構造器 this.name = name println("第一個輔助構造器") } def this(name:String ,age:Int){ this(name) //還可以調用其他輔助構造器 this.name = name this.age = age println("第二個輔助構造器") } println("name=" + name + " age=" + age) def show = { "name!=" + name + " age!=" + age } } object Test43 extends App{ var c = new TestClass43("wangwu",90) // println("name=" + c.name) // println("age=" + c.age) println(c.show) }
8.對象
定義:Object是一種類型,與class非常相似。
Object可以提供java中的靜态字段、靜态方法的功能。
伴生對象
/** * 伴生對象 */ class TestObject51 { private var value = 10 def display{ println(TestObject51.value) } def show(a:TestObject51){ //自定義getter方法 this.value = TestObject51.value } } /*伴生對象*/ object TestObject51{ //對象使用object定義 //該對象作為同名類的伴生對象 // private[this] var value = 10 private var value = 10 private def show { println("超人") } } object Test51 extends App{ // println(TestObject51.value) //不能通路對象中的私有字段 // println(TestObject51.show) }
apply 方法:
f(arg1,arg2,**)是函數調用方法,用着非常好用,如果f是類的執行個體,相當于調用類的apply()方法。
/** * apply方法 */ object Test52 extends App{ // var arr = new Array[Int](5) var arr = Array.apply(1,2,3,4) //構造數組使用的是apply方法 var map = Map.apply[String,Int]("zhangsan"->12) }
9.高階函數
1.函數可以賦給變量值
首先,在scala中,函數是一等公民
2.匿名函數:
函數的形式是(形參清單)=>傳回值類型
var ff = (s: string) => s.toUpperCase
println(ff)
/** * 高階函數 */ object Test61 extends App{ //函數定義 def add(a:Int ,b:Int) = { a + b } // var c = add(1,2) // println(c) var func1 = add _ //把一個函數的實作傳遞給另外一個函數 // println(func1(1,2)) // var func2 = (x :Int) => x + 3 //傳遞一個匿名函數給給一個變量 // var func3 = (x :Int) => {x + 3} //傳遞一個匿名函數給給一個變量 // var func4 = (x :Int) => (x + 3) //傳遞一個匿名函數給給一個變量 // for(i <- arr) // Map[String,Int]("zhangsan" -> 12) // println(func2(3)) // def func5(a:Int ,f:(Int)=>(Int)) = { // f(a) + 1 // } // println(func5(4,(x:Int) => {x + 2})) //傳遞一個匿名函數給該函數 //調用函數封裝舉例 // def CPU(a:Int) = { // a * 8 // } // def GPU(a:Int) = { // a + 9 // } // def compute(men:Int,CPU:(Int)=>(Int),GPU:(Int)=>(Int)) = { // men + CPU(2) + GPU(2) // } // println(compute(4,CPU,GPU)) def func6(f:(Int)=>(Int)) = { f(1) } // println(func6(_ + 2)) //簡寫條件:1.隻有一行代碼 2.隻有一個形參 3.把匿名函數作為形參 // println(func6(_ + _)) //總結“_” : // 1.代表數組每一個元素 // 2.指的是傳遞是确切的一個函數 而不是忘記給該函數傳遞參數 // 3.元組的元素取值 //思考題 // def func7 (x :Int ,y:Int) = { // (y : Int) => { // x + y // } + 2 // } // println(func7(3,4)(2)) //一些有用的函數 map foreach reduceLeft // (1 to 9).map("*" * _).foreach(println _) var c = (1 to 3).reduceLeft(_ + _) //1 + 2 + 3 println(c) }
3. 函數作為形參(demo 同上)
對于隻有一個參數的,可以隻寫函數體。
fun3(a=>a+2)
如果形參隻有一個,可以在函數體中使用_代替。
fun3(_+2)
函數作為形參的終極版本。
4.把匿名函數放在函數體内
5.一些有用的高階函數
10.繼承:
抽象類
1.抽象類不一定有抽象字段,有抽象字段或者抽象方法的類一定是抽象類,隻需要添加abstract關鍵字
2.有抽象字段一定是是抽象類(scala中字段定義時一定要初始化)
3.重寫字段時實質就是在重寫字段的setter/getter方法
覆寫方法
非抽象類覆寫方法的時候,一定使用override。
覆寫字段
抽象字段一定要有類型描述。
覆寫的時候,一定使用override。
/** * 繼承--抽象類 */ abstract class Person { //抽象類不一定有抽象字段或者抽象方法 //有抽象字段或者抽象方法的類 一定是抽象類 var name:String val age:Int def story:String } //方式一 //class Student extends Person{ //覆寫字段時實質上是覆寫了字段setter、getter方法 // var name:String = "Jeckson" //var定義的字段隻能使用var覆寫,并且var覆寫隻能是為實作的字段 // val age:Int = 20 //使用val定義的字段隻能使用val覆寫 //// def story = "dance" // // def story = "dance" //使用def定義的抽象方法可以使用def覆寫也可以使用val ,當def為無參時函數可以使用val //} //方式二 //class Student (var name:String = "Jeckson" ,val age:Int = 20 ,val story:String = "dance") extends Person object Test71 extends App{ // var c = new Student // println(c.name) // println(c.age) // println(c.story) var c = new Person { //方式三 匿名子類 var name:String = "Jeckson" //var定義的字段隻能使用var覆寫,并且var覆寫隻能是為實作的字段 val age:Int = 20 //使用val定義的字段隻能使用val覆寫 def story = "dance" // } }
匿名子類重寫超類
抽象字段和抽象方法/** * 構造順序 */ class Person1 { val age:Int = 10 var arr:Array[Int] = new Array[Int](age) //調age字段的getter方法 } //class student1 extends Person1{ // override lazy val age:Int = 18 //如果覆寫的父類不是抽象類 必須要寫override //} class student1 extends { //解決辦法③ override val age:Int = 18 //如果覆寫的父類不是抽象類 必須要寫override } with Person1 //特質 /*trait student2 { var a:Int = 10 var b:Int } trait student3{ def show = "123" } class student4 extends student2 with student3{ var b:Int = 1 }*/ object Test72 extends App{ var c = new student1 println(c.age) println(c.arr.length) //輸出18 0 解決辦法:1.字段前面添加final 2.字段前面添加lazy 3.解決辦法③ //原因: // a.主構造器和class類交織在一起 // b.子類中使用了override覆寫超類中的字段,構造子類時超類的字段值會被覆寫 // c.student1類作為student1的主構造器,調用了超類的Person1的主構造器 // d.首先,構造器将age值設定為10 // e.接着代碼往下走,為了初始化arr數組,調用了age的getter方法 // f.而age字段被重寫了,也就是說getter方法被重寫了 // g.被重寫的getter方法還沒有被初始化,确切說就是字段age還是對象在被配置設定空間時所有整型字段的初始值 // h.arr數組長度被設定為0 // i.子類Student1類構造器執行,age被指派為18 }
10 .模式比對
更好的switch case
object Test73 extends App{ // var t = (1,2,3) // var (first,second,third) = t //模式比對 // println(first) var s = "++" var result = s match { case "a" => println("超人") case "*" => 1 case "牛人" => "superman" case _ if s.contains("=") => (x:Int) => {x + 1} case _ => 0 } println(result) }
歲月裡,寒暑交替。人世間,北來南往。銘心的,雲煙的。都付往事,不念,不問。