1. 程式人生 > >Scala學習(二)——高級特性

Scala學習(二)——高級特性

是什麽 top 存儲 ref 相等 business one cti int

apply() 方法

apply方法是Scala提供的一個語法糖

  • 類名+括號,調用對象的apply方法

  • 對象名+括號,調用類的apply方法

對apply方法的簡單測試:(其中,帶 new -- class ApplyTest,不帶 new -- object ApplyTest)

class ApplyTest {
    println("class ApplyTest")
    def apply() {
        println("class APPLY method")
    }
}
object ApplyTest {
    println("object ApplyTest")
    def apply() = {
        println("object APPLY method")
        new ApplyTest()
    }
}

// 對象名+括號,調用類的apply方法
val a1 = new ApplyTest()
a1() // == a1.apply()
// 輸出 class ApplyTest, class APPLY method

// 類名+括號,調用對象的apply方法
val a2 = ApplyTest()
// 輸出 object ApplyTest, object APPLY method, class ApplyTest

val a2 = ApplyTest()
a2()
// 輸出 object ApplyTest, object APPLY method, class ApplyTest, class APPLY method

val a3 = ApplyTest
// 輸出 object ApplyTest

val a3 = ApplyTest
a3()
// 輸出 object ApplyTest, object APPLY method, class ApplyTest

單例對象

單例對象用於持有一個類的唯一實例。通常用於工廠模式。

object Timer {   
  var count = 0    
  def currentCount(): Long = {     
    count += 1     
    count   
  } 
} 

可以這樣使用:

Timer.currentCount() //1

單例對象可以和類具有相同的名稱,此時該對象也被稱為“伴生對象”。我們通常將伴生對象作為工廠使用。

下面是一個簡單的例子,可以不需要使用’new’來創建一個實例了。

class Bar(foo: String)  
object Bar {   
  def apply(foo: String) = new Bar(foo) 
} 

函數即對象

在Scala中,我們經常談論對象的函數式編程。這是什麽意思?到底什麽是函數呢?

函數是一些特質的集合。具體來說,具有一個參數的函數是Function1特質的一個實例。這個特質定義了apply()語法糖,讓你調用一個對象時就像你在調用一個函數。

object addOne extends Function1[Int, Int] {      
  def apply(m: Int): Int = m + 1      
} 
addOne(1) // 2 

這個Function特質集合下標從0開始一直到22。為什麽是22?這是一個主觀的魔幻數字(magic number)。我從來沒有使用過多於22個參數的函數,所以這個數字似乎是合理的。

apply語法糖有助於統一對象和函數式編程的二重性。你可以傳遞類,並把它們當做函數使用,而函數本質上是類的實例。

這是否意味著,當你在類中定義一個方法時,得到的實際上是一個Function*的實例?不是的,在類中定義的方法是方法而不是函數。在repl中獨立定義的方法是Function*的實例。

類也可以擴展Function,這些類的實例可以使用()調用。

class AddOne extends Function1[Int, Int] {      
  def apply(m: Int): Int = m + 1      
} 
val plusOne = new AddOne() 
plusOne(1) //2 

可以使用更直觀快捷的extends (Int => Int)代替extends Function1[Int, Int]

class AddOne extends (Int => Int) {   
  def apply(m: Int): Int = m + 1 
} 

模式匹配

這是Scala中最有用的部分之一。

匹配值

val times = 1  
times match {   
  case 1 => "one"   
  case 2 => "two"   
  case _ => "some other number" 
}

使用守衛進行匹配

times match {   
  case i if i == 1 => "one"   
  case i if i == 2 => "two"   
  case _ => "some other number" 
} 

註意我們是怎樣獲取變量’i’的值的。

在最後一行指令中的_是一個通配符;它保證了我們可以處理所有的情況。 否則當傳進一個不能被匹配的數字的時候,你將獲得一個運行時錯誤。

匹配類型

你可以使用 match來分別處理不同類型的值。

def bigger(o: Any): Any = {   
  o match {     
    case i: Int if i < 0 => i - 1     
    case i: Int => i + 1     
    case d: Double if d < 0.0 => d - 0.1     
    case d: Double => d + 0.1     
    case text: String => text + "s"   
  }
} 

匹配類成員

定義一個計算器,讓我們通過類型對它們進行分類。

def calcType(calc: Calculator) = calc match {   
  case _ if calc.brand == "HP" && calc.model == "20B" => "financial"   
  case _ if calc.brand == "HP" && calc.model == "48G" => "scientific"   
  case _ if calc.brand == "HP" && calc.model == "30B" => "business"   
  case _ => "unknown" 
} 

樣本類 Case Classes

使用樣本類可以方便得存儲和匹配類的內容。不用new關鍵字就可以創建它們。

case class Calculator(brand: String, model: String) 
val hp20b = Calculator("HP", "20b") 

樣本類基於構造函數的參數,自動地實現了相等性和易讀的toString方法。

val hp20b = Calculator("HP", "20b") 
val hp20B = Calculator("HP", "20b") 
hp20b == hp20B // true

樣本類也可以像普通類那樣擁有方法。

使用樣本類進行模式匹配

樣本類就是被設計用在模式匹配中的。讓我們簡化之前的計算器分類器的例子。

val hp20b = Calculator("HP", "20B") 
val hp30b = Calculator("HP", "30B")  
def calcType(calc: Calculator) = calc match {   
  case Calculator("HP", "20B") => "financial"   
  case Calculator("HP", "48G") => "scientific"   
  case Calculator("HP", "30B") => "business"   
  case Calculator(ourBrand, ourModel) => "Calculator: %s %s is of unknown type".format(ourBrand, ourModel) 
} 

最後一句也可以這樣寫

case Calculator(_, _) => "Calculator of unknown type" 

或者我們完全可以不將匹配對象指定為Calculator類型

case _ => "Calculator of unknown type" 

或者我們也可以將匹配的值重新命名。

case c@Calculator(_, _) => "Calculator: %s of unknown type".format(c) 

本文主要參考自Scala School-基礎知識(續)

Scala學習(二)——高級特性