一、語系
1.動態類型語言
概念:意思就是類型的檢查是在運行時做的
表現:使用變量前不需要聲明變量
舉例:JavaScript、Ruby、Python 這些都屬于動態類型語言
2.靜態類型語言
概念:意思就是類型判斷是在運行前做的(如編譯階段)
表現:使用變量前需要聲明變量
舉例:C、C++、Java、Scala 這些都屬于靜態類型語言
Scala 是以java虛擬機(JVM)為目標運行環境并將面向對象和函數式編程的最佳特性結合在一起的靜態類型編程語言。
二、概述
? 1.scala是純粹面向對象的,每個值都是對象,每個操作都是方法調用。
? 2.Scala是成熟的函數式語言:
? ? ? ? ? ? ①函數是頭等值,也就是說函數也是值,并且和其他類型(如整數、字符串等)處于同一地位,函數可以被當作參數傳遞,也可以被當作返回值返回,還可以在函數中定義函數等等;
? ? ? ? ? ②程序的操作應該把輸入值映射為輸出值而不是就地修改,也就是說函數調用不應產生副作用。
雖然函數式編程語言鼓勵使用“無副作用”的方法,但是scala并不強制你必須這么做。
? ? ? ? ? scala允許你使用指令式的編程風格,但是隨著你對scala的深入了解,你可能會更傾向于一種更為函數式的編程風格。向函數式編程轉變,你就應該盡量去使用val、不可變對象、無副作用方法,而不是var、可變對象、有副作用方法。要明白的是,從指令式編程向函數式編程的轉變會很困難,因此你要做好充分的準備,并不斷的努力。
三、基礎知識
1.在scala中,語句之后的“;”是可選的,這根據你的喜好。
? ? ? ? (當有多個語句在同一行時,必須加上分號,但不建議把多個語句放在一行。)
2.建議使用2個空格作為代碼縮進。? ? ? ? 不過我咋喜歡一個tab呢 ⊙﹏⊙!
3.在scala中,符號“_”相當于java中的通配符“*”。
4.scala類似于c++、java,索引也l是從0開始,但元組是個例外,它從1開始。
5.scala有7種數值類型:Byte、Char、Short、Int、Long、Float和Double,以及2種非數值類型:Boolean和Unit(只有一個值“()”,相當于java和c++中的void,即空值)。
? ? 5.1這些類型都是抽象的final類(不能使用new新建,也不能被繼承),在scala包中定義,是對java基本數據類型的包裝,因此與? ? ? ? ? java基本數據類型有相同的長度。
? ? 5.2 scala還提供了RichInt、RichChar等等,它們分別提供Int、Char等所不具備的便捷方法。
? ? 5.3 scala沿用了java.lang包中的String。在scala中,常量也稱作字面量,字符串字面量由雙引號包含的字符組成。
? ? 5.4原始字符串,它以三個雙引號作為開始和結束,字符串內部可以包含無論何種任意字符。
6.scala有兩種變量:val和var。val如同java中的final變量,var如同java中的非final變量。
? ? 6.1 由于scala是完全面向對象的,因此val和var只是聲明了對象的引用是不可變的還是可變的,并不能說明引用指向的對象的可? ? ? ? 變性;
? ? 6.2 聲明變量的同時需要初始化之,否則該變量就是抽象的;
? ? 6.3 如果不指定變量的類型,編譯器會從初始化它的表達式中推斷出其類型。當然你也可以在必要的時候指定其類型,但注意,在scala中變量或函數的類型總是寫在變量或函數的名稱的后邊。例如:val answer = “yes”;val answer, message: String = “yes”;
7.scala標識符有四種形式:字母數字標識符、操作符標識符、混合標識符、字面量標識符。
? ? ? ? ? 字母數字標識符:跟其他語言類似,由字母、數字和下劃線組成,但需注意“$”字符被保留作為scala編譯器產生的標識符之用,你不要隨意使用它啊。
? ? ? ? 操作符標識符:由一個或多個操作符字符組成。scala編譯器將在內部“粉碎”操作符標識符以轉換成合法的內嵌“$”的java標識符。若你想從java代碼中訪問這個標識符,就應該使用這種內部表示方式。
? ? ? ? 混合標識符:由字母數字以及后面跟著的下劃線和一個操作符標識符組成。如unary_+定義了一個前綴操作符“+”。
? 注意scala并不提供++、--操作符。但可寫為,如 a + b 相當于 a.+(b)。
? ? ? ? 字面量標識符:是用反引號`…`包含的任意字符串,scala將把被包含的字符串作為標識符,即使被包含字符串是scala的關鍵字。例如:你可以使用Thread.`yield`()來訪問java中的方法,即使yield是scala的關鍵字。
8.在scala中,{}塊包含一系列表達式,其結果也是一個表達式,塊中最后一個表達式的值就是其值。
? ? ? ? 在scala中,賦值語句本身的值是Unit類型的。因此如下語句的值為“()”:{r = r * n; n -= 1}。因此,scala中不能多重賦值。
如下語句中的x值為“()”:x = y = 1
9.scala和其他編程語言有一個根本性差異:
? ? ? ? 在scala中,幾乎所有構造出來的語法結構都有值。這個特性使得程序結構更加精簡。scala內建的控制結構很少,僅有if、while、for、try、match和函數調用等而已。如此之少的理由是,scala從語法層面上支持函數字面量。
? ? 9.1.1 if表達式:
? ? ? ? scala的if/else語法結構與java等一樣,但是在scala中if/else表達式有值,這個值就是跟在if/esle后邊的表達式的值。如下:
? ? ? ? val s = if(x > 0) 1 else -1
? ? ? 9.1.2 同時注意:scala的每個表達式都有一個類型,比如上述if/esle表達式的類型是Int。
? ? ? ? ? 如果是混合類型表達式,則表達式的類型是兩個分支類型的公共超類型。
? ? ? ? ? String和Int的超類型就是Any。如果一個if語句沒有else部分,則當if條件不滿足時,表達式結果為Unit。如:if(x > 0) 1
? ? ? ? ? ? 就相當于:if(x > 0) 1 else ()?
? ? ? ? ? 備注:Unit 表示無值,和其他語言中void等同。用作不返回任何結果的方法的結果類型。Unit只有一個實例值,寫成()。
? ? 9.2 while循環:scala擁有與java和c++中一樣的while和do-while循環,while、do-while結果類型是Unit。
? ? 9.3 for表達式:scala中沒有類似于for(; ; )的for循環,你可以使用如下形式的for循環語句:for(i <- 表達式)
? ? ? ? ? 該for表達式語法對于數組和所有集合類均有效。具體介紹如下:
? ? ? ? ? 9.3.1 枚舉:for(i <- 1 to 10),其中“i <- 表達式”語法稱之為發生器,該語句是讓變量i(注意此處循環變量i是val的(但無需你? ? ? ? ? ? ? ? ? 指定),該變量的類型是集合的元素類型)遍歷表達式中的所有值。1 to 10產生的Range包含上邊界,如果不想包含上? ? ? ? ? ? ? ? ? ? 邊界,可以使用until。
? ? ? ? ? 9.3.2 過濾:也叫守衛,在for表達式的發生器中使用過濾器可以通過添加if子句實現,如:for(i <- 1 to 10 if i!=5),如果要添? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 加多個過濾器,即多個if子句的話,要用分號隔開,如:for(i <- 1 to 10 if i!=5; if i!=6)。
? ? ? ? ? 9.3.3 嵌套枚舉:如果使用多個“<-”子句,你就得到了嵌套的“循環”,如:for(i <- 1 to 5; j <- 1 to i)。
? ? ? ? ? 9.3.4? 流間變量綁定:你可以在for發生器以及過濾器等中使用變量保存計算結果,以便在循環體中使用,從而避免多次計算? ? ? ? ? ? ? ? ? ? ? 以得到該結果。流間變量綁定和普通變量定義相似,它被當作val,但是無需聲明val關鍵字。
? ? ? ? 9.3.5 制造新集合:for(…) yield 變量/循環體,最終將產生一個集合對象,集合對象的類型與它第一個發生器的類型是兼容的。
? ? ? ? ? 9.3.6 實際上:for表達式具有等價于組合應用map、flatMap、filter和foreach這幾種高階函數的表達能力。
? ? ? ? ? ? ? ? 實際上,所有的能夠yield(產生)結果的for表達式都會被編譯器轉譯為高階方法map、flatMap及filter的組合調用;
? ? ? ? ? ? ? ? 所有的不帶yield的for循環都會被轉譯為僅對高階函數filter和foreach的調用。正是由于這幾個高階函數支持了for表達式,? ? ? ? ? ? ? ? ? 所以如果一個數據類型要支持for表達式,它就要定義這幾個高階函數。有些時候,你可以使用for表達式代替map、? ? ? ? ? ? ? ? ? ? ? ? ? flatMap、filter和foreach的顯式組合應用,或許這樣會更清晰明了呢。
10. scala中沒有break和continue語句。如果需要類似的功能時,我們可以:
? ? ? ? 1) 使用Boolean類型的控制變量
? ? ? ? 2) 使用嵌套函數,你可以從函數當中return
11.? match表達式與模式匹配:
? ? ? 11.1scala中沒有switch,但有更強大的match。它們的主要區別在于:
? ? ? ① 任何類型的常量/變量,都可以作為比較用的樣本;
? ? ? ② 在每個case語句最后,不需要break,break是隱含的;?
? ? ? ③ 更重要的是match表達式也有值;
? ? ? ④ 如果沒有匹配的模式,則MatchError異常會被拋出。
? ? ? 11.2? match表達式的形式為:選擇器 match { 備選項 }。
? ? ? ? ? ? ? 一個模式匹配包含了一系列備選項,每個都開始于關鍵字case。
? ? ? ? ? ? 每個備選項都包含了一個模式以及一到多個表達式,它們將在模式匹配過程中被計算。箭頭符號“=>”隔開了模式和表達? ? ? ? ? ? ? ? ? ? 式。按照代碼先后順序,一旦一個模式被匹配,則執行“=>”后邊的表達式((這些)表達式的值就作為match表達式的值),? ? ? ? ? ? ? ? ? ? 后續case語句不再執行。示例如下:
? ? ? ? ? ? a match {
? ? ? ? ? ? ? ? ? case 1 => "match 1"
? ? ? ? ? ? ? ? case _ => "match _"
? ? ? ? ? }
? ? ? ? 11.3 match模式的種類如下:
? ? ? ? ? ? ? ? ① 通配模式:可以匹配任意對象,一般作為默認情況,放在備選項最后,如:case _ =>
? ? ? ? ? ? ? ? ② 變量模式:類似于通配符,可以匹配任意對象,不同的是匹配的對象會被綁定在變量上,之后就可以使用這個變量操? ? ? ? ? ? ? ? ? ? ? 作對象。所謂變量就是在模式中臨時生成的變量,不是外部變量,外部變量在模式匹配時被當作常量使用,見常量模? ? ? ? ? ? ? ? ? ? ? ? 式。注意:同一個模式變量只能在模式中出現一次。
? ? ? ? ? ? ? ③ 常量模式:僅匹配自身,任何字面量都可以作為常量,外部變量在模式匹配時也被當作常量使用,
? ? ? ? ? ? ? ? 如:case "false" => "false"
? ? ? ? ? ? ? ? ? ? ? case true => "truth"
? ? ? ? ? ? ? ? ? ? ? case Nil => "empty list"
? ? ? ? ? ? ? 對于一個符號名,是變量還是常量呢?scala使用了一個簡單的文字規則對此加以區分:用小寫字母開始的簡單名被當作? ? ? ? ? ? ? ? 是模式變量,所有其他的引用被認為是常量。如果常量是小寫命名的外部變量,那么它就得特殊處理一下了:如果它是對? ? ? ? ? ? ? ? 象的字段,則可以加上“this.”或“obj.”前綴;或者更通用的是使用字面量標識符解決問題,也即用反引號“`”包圍之。
? ? ? ? ? ? ④ 抽取器模式:抽取器機制基于可以從對象中抽取值的unapply或unapplySeq方法,其中,unapply用于抽取固定數量的東? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 東,unapplySeq用于抽取可變數量的東東,它們都被稱為抽取方法,抽取器正是通過隱式調用抽取方法抽取出? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 對應東東的。抽取器中也可以包含可選的apply方法,它也被稱作注入方法,注入方法使你的對象可以當作構造? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 器? ? 來用,而抽取方法使你的對象可以當作模式來用,對象本身被稱作抽取器,與是否具有apply方法無關。樣本? ? ? ? ? ? ? ? ? ? ? ? ? ? 類會自動生成伴生對象并添加一定的句法以作為抽取器,實際上,你也可以自己定義一個任意其他名字的單例對? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 象作為抽取器使用,以這樣的方式定義的抽取器對象與樣本類類型是無關聯的。你可以對數組、列表、元組進行模? ? ? ? ? ? ? ? ? ? ? ? ? ? 式匹配,這正是基于抽取器模式的。
? ? ? ? ? ? ⑤ 類型模式:你可以把類型模式當作類型測試和類型轉換的簡易替代,示例如下:
? ? ? ? ? ? ? ? ? ? ? ? ? case s: String => s.length
? ? ? ? ? ? ⑥ 變量綁定:除了獨立的變量模式之外,你還可以把任何其他模式綁定到變量。只要簡單地寫上變量名、一個@符號,以? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 及這個模式。
? ? ? ? ? ? ? 模式守衛:模式守衛接在模式之后,開始于if,相當于一個判斷語句。守衛可以是任意的引用模式中變量的布爾表達式。? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 如果存在模式守衛,只有在守衛返回true的時候匹配才算成功。
? ? ? ? ? ? ? Option類型:scala為可選值定義了一個名為Option的標準類型,一個Option實例的值要么是Some類型的實例,要么是? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? None對象。分離可選值最通常的辦法是通過模式匹配,如下:
? ? ? ? ? ? ? ? ? case Some(s) => s
? ? ? ? ? ? ? ? ? case None => “?”
? ? ? ? ? ? 模式無處不在:在scala中,模式可以出現在很多地方,而不單單在match表達式里。比如:
? ? ? ? ? ? ? ? ? ? ① 模式使用在變量定義中,如下:
? ? ? ? ? ? ? ? ? ? ? val myTuple = (123, “abc”)
? ? ? ? ? ? ? ? ? ? ? val (number, string) = myTuple
? ? ? ? ? ? ? ② 模式匹配花括號中的樣本序列(即備選項)可以用在能夠出現函數字面量的任何地方,實質上,樣本序列就是更普遍的函? ? ? ? ? ? ? ? ? ? 數字面量,函數字面量只有一個入口點和參數列表,樣本序列可以有多個入口點,每個都有自己的參數列表,每個樣本? ? ? ? ? ? ? ? ? ? 都是函數的一個入口點,參數被模式所特化。如下:
? ? ? ? ? ? ? ? ? ? val withDefault: Option[Int] => String = {
? ? ? ? ? ? ? ? ? ? ? ? ? case Some(x) => "is int"
? ? ? ? ? ? ? ? ? ? ? ? ? case None => "?"
? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ③ for表達式里也可以使用模式。示例如下:
? ? ? ? ? ? ? ? ? ? ? for((number, string) <- myTuple) println(number + string)
? ? ? ? ? ? ? ? ? ? ? ? 模式匹配中的中綴標注:帶有兩個參數的方法可以作為中綴操作符使用,使用中綴操作符時實際上是其中一個操作? ? ? ? ? ? ? ? ? ? ? ? ? ? 數在調用操作符對應的方法,而另一個操作數作為方法的參數。但對于模式來說規則有些不同:如果被當作模式,? ? ? ? ? ? ? ? ? ? ? ? ? ? 那么類似于p op q這樣的中綴標注等價于op(p,q),也就是說中綴標注符op被用做抽取器模式。
文章最后發布于: 2018-08-05