Scala 基礎(1)—— 定義變量 & 定義函數


1. 使用 val & var 定義變量

Scala 中的變量被分為2種:val 和 var。其含義於 Java 中的 final 關鍵字類似。

val 等同於被 final 修飾過的變量, 即一旦初始化便不可被重新賦值。

var 等同於未被 final 修飾過的變量,可以被重新賦值。

1   def main(args: Array[String]): Unit = {
2     val x = 1
3     x = 2 // 編譯錯誤
4   }

 

1   def main(args: Array[String]): Unit = {
2     var x = 1
3     x = 2 // 編譯成功
4   }

 

與 Java 相同,這里的所謂不變性,是指引用不可變但是引用對象的狀態卻是可變的。

object Demo {

  def main(args: Array[String]): Unit = {
    val a = new A(1)
    a.x = 3
    println(a.x)
  }
}

class A(myX: Int) {
  var x: Int = myX
}

以上的例子,輸出結果為3。

 

 

2. 類型推斷

可以看出這里有一個很明顯的與 Java 不同的地方:在聲明變量的時候,沒有顯式地給出類型

Scala 支持類型推斷,就是它能夠根據等式右側的值來推斷出這個參數的類型,例如上面的例子,x 的類型就是 scala.Int。

如果這並不是你所希望的 x 類型,例如,你期望初始化一個 Double 類型的,可以這么定義:

val x: Double = 1

 

需要注意的是,如果只希望聲明變量,而不同時對變量進行初始化(一般來說這種情況只存在於定義成員變量),那么就必須顯式定義類型,因為沒有等式右側去推測這個參數的實際類型。

abstract class MyClass {
  val y: Int
}

 

 

3. 強調參數可變性的意義

Scala 之所以使用 val 和 var 來定義參數,主要就是為了在聲明變量時,就確定它的可變性。

Scala 推薦能使用 val 的地方就是用 val,這么做的優勢有:

  • Scala 是一門支持函數式編程的語言,將變量定義成 val,可以有效地規避/減少函數的副作用。
  • 將成員變量定義成 val,可以保證構造的對象是不可變對象,這個性質在多線程編程中很有用。

關於不可變對象,可以參考《Java 並發編程實戰》P38(因為 Scala 是運行在 JVM 平台上的,編譯之后本質其實就是 Java 的字節碼文件)

當滿足以下條件時,獨享才是不可變的:

  • 對象創建以后其狀態就不能改變。
  • 對象的所有域都是 final 類型的。
  • 對象是正確創建的(在對象創建期間,this 引用沒有溢出)。

 

 

4. 使用 def 定義函數

我們觀察以下函數的定義:

  def max(x: Int, y: Int): Int = {
    if (x > y) x else y
  }

 

定義一個函數包括以下部分:

  • def -> 定義函數的關鍵字
  • max -> 函數名
  • x: Int, y: Int -> 參數列表
  • Int -> 函數的結果類型
  • if (x > y) x else y -> 函數體

 

 

5. 函數的結果類型

由於 Scala 的類型推斷機制,函數的結果類型是可以省略的,也就是說沒這么定義函數也是可行的:

  def max(x: Int, y: Int) = {
    if (x > y) x else y
  }

 

但是,有一種例外,就是遞歸地函數,必須給出結果類型:

  def factorial(x: Int) = {
    require(x >= 0)
    if (x > 1) x * factorial(x - 1) else 1 // 編譯錯誤
  }

雖然如此,但是一般推薦所有可以被外部訪問的函數(等價於 Java 中的 public),都顯式地加上結果類型。 

 

在上面 main 函數的例子中,結果類型 Unit 等價於 Java 中的 Void,表示函數並不會返回有實際意義的結果。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM