亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

characters

    apply 方法

    當(dāng)類或?qū)ο笥幸粋€(gè)主要用途的時(shí)候,apply方法為你提供了一個(gè)很好的語法糖。

    scala> class Foo {}
    defined class Foo
    
    scala> object FooMaker {
         |   def apply() = new Foo
         | }
    defined module FooMaker
    
    scala> val newFoo = FooMaker()
    newFoo: Foo = Foo@5b83f762

    scala> class Bar {
         |   def apply() = 0
         | }
    defined class Bar
    
    scala> val bar = new Bar
    bar: Bar = Bar@47711479
    
    scala> bar()
    res8: Int = 0

    在這里,我們實(shí)例化對(duì)象看起來像是在調(diào)用一個(gè)方法。以后會(huì)有更多介紹!

    單例對(duì)象

    單例對(duì)象用于持有一個(gè)類的唯一實(shí)例。通常用于工廠模式。

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

    可以這樣使用:

    scala> Timer.currentCount()
    res0: Long = 1

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

    下面是一個(gè)簡(jiǎn)單的例子,可以不需要使用’new’來創(chuàng)建一個(gè)實(shí)例了。

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

    函數(shù)即對(duì)象

    在Scala中,我們經(jīng)常談?wù)搶?duì)象的函數(shù)式編程。這是什么意思?到底什么是函數(shù)呢?

    函數(shù)是一些特質(zhì)的集合。具體來說,具有一個(gè)參數(shù)的函數(shù)是Function1特質(zhì)的一個(gè)實(shí)例。這個(gè)特征定義了apply()語法糖,讓你調(diào)用一個(gè)對(duì)象時(shí)就像你在調(diào)用一個(gè)函數(shù)。

    scala> object addOne extends Function1[Int, Int] {
         |   def apply(m: Int): Int = m + 1
         | }
    defined module addOne
    
    scala> addOne(1)
    res2: Int = 2

    這個(gè)Function特質(zhì)集合下標(biāo)從0開始一直到22。為什么是22?這是一個(gè)主觀的魔幻數(shù)字(magic number)。我從來沒有使用過多于22個(gè)參數(shù)的函數(shù),所以這個(gè)數(shù)字似乎是合理的。

    apply語法糖有助于統(tǒng)一對(duì)象和函數(shù)式編程的二重性。你可以傳遞類,并把它們當(dāng)做函數(shù)使用,而函數(shù)本質(zhì)上是類的實(shí)例。

    這是否意味著,當(dāng)你在類中定義一個(gè)方法時(shí),得到的實(shí)際上是一個(gè)Function*的實(shí)例?不是的,在類中定義的方法是方法而不是函數(shù)。在repl中獨(dú)立定義的方法是Function*的實(shí)例。

    類也可以擴(kuò)展Function,這些類的實(shí)例可以使用()調(diào)用。

    scala> class AddOne extends Function1[Int, Int] {
         |   def apply(m: Int): Int = m + 1
         | }
    defined class AddOne
    
    scala> val plusOne = new AddOne()
    plusOne: AddOne = <function1>
    
    scala> plusOne(1)
    res0: Int = 2

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

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

    你可以將代碼組織在包里。

    package com.twitter.example

    在文件頭部定義包,會(huì)將文件中所有的代碼聲明在那個(gè)包中。

    值和函數(shù)不能在類或單例對(duì)象之外定義。單例對(duì)象是組織靜態(tài)函數(shù)(static function)的有效工具。

    package com.twitter.example
    
    object colorHolder {
      val BLUE = "Blue"
      val RED = "Red"
    }

    現(xiàn)在你可以直接訪問這些成員

    println("the color is: " + com.twitter.example.colorHolder.BLUE)

    注意在你定義這個(gè)對(duì)象時(shí)Scala解釋器的返回:

    scala> object colorHolder {
         |   val Blue = "Blue"
         |   val Red = "Red"
         | }
    defined module colorHolder

    這暗示了Scala的設(shè)計(jì)者是把對(duì)象作為Scala的模塊系統(tǒng)的一部分進(jìn)行設(shè)計(jì)的。

    模式匹配

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

    匹配值

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

    使用守衛(wèi)進(jìn)行匹配

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

    注意我們是怎樣將值賦給變量’i’的。

    在最后一行指令中的_是一個(gè)通配符;它保證了我們可以處理所有的情況。
    否則當(dāng)傳進(jìn)一個(gè)不能被匹配的數(shù)字的時(shí)候,你將獲得一個(gè)運(yùn)行時(shí)錯(cuò)誤。我們以后會(huì)繼續(xù)討論這個(gè)話題的。

    參考 Effective Scala 對(duì)什么時(shí)候使用模式匹配 和 模式匹配格式化的建議. A Tour of Scala 也描述了 模式匹配

    匹配類型

    你可以使用 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"
      }
    }

    匹配類成員

    還記得我們之前的計(jì)算器嗎。

    讓我們通過類型對(duì)它們進(jìn)行分類。

    一開始會(huì)很痛苦。

    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"
    }

    (⊙o⊙)哦,太痛苦了。幸好Scala提供了一些應(yīng)對(duì)這種情況的有效工具。

    樣本類 Case Classes

    使用樣本類可以方便得存儲(chǔ)和匹配類的內(nèi)容。你不用new關(guān)鍵字就可以創(chuàng)建它們。

    scala> case class Calculator(brand: String, model: String)
    defined class Calculator
    
    scala> val hp20b = Calculator("hp", "20b")
    hp20b: Calculator = Calculator(hp,20b)

    樣本類基于構(gòu)造函數(shù)的參數(shù),自動(dòng)地實(shí)現(xiàn)了相等性和易讀的toString方法。

    scala> val hp20b = Calculator("hp", "20b")
    hp20b: Calculator = Calculator(hp,20b)
    
    scala> val hp20B = Calculator("hp", "20b")
    hp20B: Calculator = Calculator(hp,20b)
    
    scala> hp20b == hp20B
    res6: Boolean = true

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

    使用樣本類進(jìn)行模式匹配

    case classes are designed to be used with pattern matching.  Let’s simplify our calculator classifier example from earlier.
    樣本類就是被設(shè)計(jì)用在模式匹配中的。讓我們簡(jiǎn)化之前的計(jì)算器分類器的例子。

    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"

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

      case _ => "Calculator of unknown type"

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

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

    異常

    Scala中的異??梢栽趖ry-catch-finally語法中通過模式匹配使用。

    try {
      remoteCalculatorService.add(1, 2)
    } catch {
      case e: ServerIsDownException => log.error(e, "the remote calculator service is unavailable. should have kept your trusty HP.")
    } finally {
      remoteCalculatorService.close()
    }

    try也是面向表達(dá)式的

    val result: Int = try {
      remoteCalculatorService.add(1, 2)
    } catch {
      case e: ServerIsDownException => {
        log.error(e, "the remote calculator service is unavailable. should have kept your trusty HP.")
        0
      }
    } finally {
      remoteCalculatorService.close()
    }

    這并不是一個(gè)完美編程風(fēng)格的展示,而只是一個(gè)例子,用來說明try-catch-finally和Scala中其他大部分事物一樣是表達(dá)式。

    當(dāng)一個(gè)異常被捕獲處理了,finally塊將被調(diào)用;它不是表達(dá)式的一部分。

Previous article: Next article: