天天看點

Scala基礎入門-1

首先需要Scala開發環境的搭建,網上自己找教程。

  

在Scala中,更加鼓勵使用val來進行聲明,也就是推薦使用常量。在大部分時候不需要分号,看自己便好…雖然是強靜态類型的語言,但是卻并沒有寫出類型——這就是類型推斷。

也可以指定類型:

多個的同時聲明:

與Java類似,Scala中也有表示數值類型的類,但是Scala不區分基本類型和引用類型。也就是說Scala中一切都是對象了吧。

Scala對Java中的數值類型的功能添加了許多功能上的強化,這其中涉及了隐式轉換。比如,String類型轉換成StringOps類型。還有RichInt、RichDouble等對應Int、Double類型。至于有什麼新加的方法,可以檢視Scala API。

算數操作符應該與預期中的沒有什麼差異,因為如果有差異用起來就有麻煩了。但算數操作符事實上是方法。

對于帶有一個隐式參數和一個顯式參數的方法來說,通常都可以這麼簡化。如:

兩種風格任君選擇。

Scala沒有提供++和–(别認為我打錯了,這裡是有兩個-号的)這兩個其他語言中很常見常用的操作符,理由是:不值得為少按一個鍵而額外增加一個特例。

Scala中可以對操作符進行重載。

函數(function)和方法(method)

引入相應的包後,使用函數很簡單,不需要從某個類中調用靜态方法。

Scala中沒有靜态方法,但是有單例對象和伴生對象之類的概念可以實作差不多的特性,這些估計到後面會細說。

通常,使用沒有參數,且不改變目前對象的方法時,不帶圓括号。

s是一個字元串,而 s(4) 将會傳回該字元串中第4個字元。在使用形如 s(4) 這種,類似于函數調用的文法時,實際上是調用了 apply() 方法。也就是說, s(4) 等于 s.apply(4)

兩個容易混淆的概念——表達式(expression)和語句(statement)。表達式有值,而語句沒有值隻執行操作。

要說起這一點的原因是,Scala中,幾乎所有構造出來的文法結構都有值,也就是表達式。這可以使程式更加精簡易讀。

舉例,if表達式是有值的;語句塊也是有值的,是最後一個表達式的值。

而對應Java中的void,Scala中有一個類型Unit,用來表示“無有用值”(void表示沒有值,這裡還是有差别的)。

if/else表達式在Scala中是有值的,除開這一點,與Java等語言沒有什麼差别。而有值所帶來的效果,可以是下面這樣子的:

第一種寫法可以用來初始化一個val,而第二種則要求s必須是var。前面也說了,Scala中更鼓勵使用val。

同時,這樣的條件表達式,還可以實作比三目操作符 ? : 更加靈活的功能。

如果在if和else兩邊的類型是不同的,比如:

這時傳回的類型将會是兩個分支類型的公共超類型(這裡是String和Int的公共超類型Any)。

如果沒有else部分,那麼if表達式有可能不傳回值,這時候就需要前面提到的Unit類型,寫做()。

分号不是必須的,但是使用它們不會帶來壞處。

能根據上下文判斷出語句結尾的地方,都不需要使用分号。怎麼判斷是否語句結尾,以後在編碼過程中會慢慢積累起感覺的。

如果需要在單行中寫多個語句,那麼就需要使用分号了。而在寫一個較長的語句時,如果需要分行寫,要確定前面的行尾需要以不能用來語句結尾的符号來結束。比如說像是下面的操作符:

這裡還可以發現的是,Scala推薦使用兩個空格來縮進。

由于判斷語句終止的需要,Scala程式員更傾向于使用Kernighan & Ritchie風格的花括号(也就是Java中推薦的方法):

Scala中,{ }包含一系列的表達式,而且{ }最後傳回的也是一個表達式——最後一個表達式。

而指派語句的值,是Unit類型的。這也大體上決定了在Java和C++中的 x = y = 1 會出現的指派語句,幾乎不可能出現在Scala中。

輸入函數: readLine()、 readInt()等,用來從控制台Console中讀取輸入。

而輸出部分,則是很常見的 print()、 println()、 printf()。

看看Scala中的for循環:

事實上,Scala中更多是使用函數式而不是指令式的風格來周遊等操作。後面會見到的。

在一個for循環中使用多個“generator”(生成器):

在for循環中使用“filter ”(過濾器,守衛)來過濾一部分不符合條件的枚舉情況:

可以使用多個filter,中間需要使用分号分隔。

可以在for表達式中使用任意多的定義,引入在循環中使用變量:

如果for表達式的循環體是以yield關鍵詞開始的,那麼該循環會構造出一個集合,這被稱為for推導式。推導式生成的集合與第一個generator是類型相容的。

還可以将for表達式的小括号換成花括号,這樣可以省去寫分号的功夫。

for表達式内容不少,而且這裡也不是全部。在《Programming in Scala》中,還有一些進階的讨論,這裡就先略了,先入個門。

在Java中并沒有函數這個概念,函數的功能是用靜态方法來實作的。

函數的定義:

隻要函數不是遞歸的,就不需要給出函數的傳回值類型(因為有類型推斷)。一個遞歸的函數需要如下寫:

在Scala中,并不時常使用return來傳回值。

Java裡似乎沒有預設參數和帶名參數,至少我從來沒有使用過。但記得C++是有的。

上面的函數有兩個帶有預設值的參數left和right。如果不給出這兩個參數,調用這個函數,會使用預設值。也可以給出自己的參數來替代預設的。

參數個數不夠時,将會從後往前使用預設參數。

調用函數時,如果指定參數名,那麼參數可以不按照參數清單的順序來:

decorate("Hello", right = "]<<<")

從上面還可以知道,可以混用未命名參數和帶名參數。

星号表示可接受變長參數清單。函數實際得到的參數是Seq類型的。

但是在調用變長參數函數時,并不能直接使用Seq類型的參數。要将一個Seq類型打散成單個的參數序列,使用 : _*。

過程的定義與函數很類似。函數體在花括号中,而且花括号前沒有=号,傳回值是Unit類型的,這就是過程了。(也可以寫出=号,并且寫明傳回值是Unit類型來定義過程。)

通常,過程沒有傳回值,隻是為了副作用而調用一個過程。

當val被聲明為lazy時,初始化會被推遲到首次對其取值時。

如果程式一直不妨問words,那麼Scala也不會去打開那個檔案。檔案是在實際第一次使用words時被打開的。

懶值對開銷較大的初始化語句十分有用,可以應對一些初始化問題比如循環依賴。還是開發懶資料結構的基礎。

可以将懶值當成是介于val和def的中間狀态:

val在被定義時即被取值

lazy val在首次使用時被取值

def在每次使用時取值

Scala中異常機制與Java和C++中一樣。但Scala中并沒有受檢異常,也就是不需要說明函數方法可能會抛出什麼異常。

使用throw來抛出一個異常。throw表達式的類型是Nothing。

捕獲異常:

如果不需要使用捕獲的異常對象,使用_來代替變量名(_是Scala中的通配符)。

同時也有try/finally語句,通常用來清理。可以組合成try/catch/finally語句

fRom: http://nerd-is.in/2013-08/scala-learning-control-structures-and-functions/