<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                課程內容: [TOC=3,3] ## 關于這節課 最初的幾個星期將涵蓋基本語法和概念,然后我們將通過更多的練習展開這些內容。 有一些例子是以解釋器交互的形式給出的,另一些則是以源文件的形式給出的。 安裝一個解釋器,可以使探索問題空間變得更容易。 ### 為什么選擇 Scala? * 表達能力 * 函數是一等公民 * 閉包 * 簡潔 * 類型推斷 * 函數創建的文法支持 * Java互操作性 * 可重用Java庫 * 可重用Java工具 * 沒有性能懲罰 ### Scala 如何工作? * 編譯成Java字節碼 * 可在任何標準JVM上運行 * 甚至是一些不規范的JVM上,如Dalvik * Scala編譯器是Java編譯器的作者寫的 ### 用 Scala 思考 Scala不僅僅是更好的Java。你應該用全新的頭腦來學習它,你會從這些課程中認識到這一點的。 ### 啟動解釋器 使用自帶的`sbt console`啟動。 ~~~ $ sbt console [...] Welcome to Scala version 2.8.0.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_20). Type in expressions to have them evaluated. Type :help for more information. scala> ~~~ ## 表達式 ~~~ scala> 1 + 1 res0: Int = 2 ~~~ res0是解釋器自動創建的變量名稱,用來指代表達式的計算結果。它是Int類型,值為2。 Scala中(幾乎)一切都是表達式。 ## 值 你可以給一個表達式的結果起個名字賦成一個不變量(val)。 ~~~ scala> val two = 1 + 1 two: Int = 2 ~~~ 你不能改變這個不變量的值. ### 變量 如果你需要修改這個名稱和結果的綁定,可以選擇使用`var`。 ~~~ scala> var name = "steve" name: java.lang.String = steve scala> name = "marius" name: java.lang.String = marius ~~~ ## 函數 你可以使用def創建函數. ~~~ scala> def addOne(m: Int): Int = m + 1 addOne: (m: Int)Int ~~~ 在Scala中,你需要為函數參數指定類型簽名。 ~~~ scala> val three = addOne(2) three: Int = 3 ~~~ 如果函數不帶參數,你可以不寫括號。 ~~~ scala> def three() = 1 + 2 three: ()Int scala> three() res2: Int = 3 scala> three res3: Int = 3 ~~~ ### 匿名函數 你可以創建匿名函數。 ~~~ scala> (x: Int) => x + 1 res2: (Int) => Int = <function1> ~~~ 這個函數為名為x的Int變量加1。 ~~~ scala> res2(1) res3: Int = 2 ~~~ 你可以傳遞匿名函數,或將其保存成不變量。 ~~~ scala> val addOne = (x: Int) => x + 1 addOne: (Int) => Int = <function1> scala> addOne(1) res4: Int = 2 ~~~ 如果你的函數有很多表達式,可以使用{}來格式化代碼,使之易讀。 ~~~ def timesTwo(i: Int): Int = { println("hello world") i * 2 } ~~~ 對匿名函數也是這樣的。 ~~~ scala> { i: Int => println("hello world") i * 2 } res0: (Int) => Int = <function1> ~~~ 在將一個匿名函數作為參數進行傳遞時,這個語法會經常被用到。 ### 部分應用(Partial application) 你可以使用下劃線“_”部分應用一個函數,結果將得到另一個函數。Scala使用下劃線表示不同上下文中的不同事物,你通常可以把它看作是一個沒有命名的神奇通配符。在`{ _ + 2 }`的上下文中,它代表一個匿名參數。你可以這樣使用它: ~~~ scala> def adder(m: Int, n: Int) = m + n adder: (m: Int,n: Int)Int ~~~ ~~~ scala> val add2 = adder(2, _:Int) add2: (Int) => Int = <function1> scala> add2(3) res50: Int = 5 ~~~ 你可以部分應用參數列表中的任意參數,而不僅僅是最后一個。 ### 柯里化函數 有時會有這樣的需求:允許別人一會在你的函數上應用一些參數,然后又應用另外的一些參數。 例如一個乘法函數,在一個場景需要選擇乘數,而另一個場景需要選擇被乘數。 ~~~ scala> def multiply(m: Int)(n: Int): Int = m * n multiply: (m: Int)(n: Int)Int ~~~ 你可以直接傳入兩個參數。 ~~~ scala> multiply(2)(3) res0: Int = 6 ~~~ 你可以填上第一個參數并且部分應用第二個參數。 ~~~ scala> val timesTwo = multiply(2) _ timesTwo: (Int) => Int = <function1> scala> timesTwo(3) res1: Int = 6 ~~~ 你可以對任何多參數函數執行柯里化。例如之前的`adder`函數 ~~~ scala> (adder _).curried res1: (Int) => (Int) => Int = <function1> ~~~ ### 可變長度參數 這是一個特殊的語法,可以向方法傳入任意多個同類型的參數。例如要在多個字符串上執行String的`capitalize`函數,可以這樣寫: ~~~ def capitalizeAll(args: String*) = { args.map { arg => arg.capitalize } } scala> capitalizeAll("rarity", "applejack") res2: Seq[String] = ArrayBuffer(Rarity, Applejack) ~~~ ## 類 ~~~ scala> class Calculator { | val brand: String = "HP" | def add(m: Int, n: Int): Int = m + n | } defined class Calculator scala> val calc = new Calculator calc: Calculator = Calculator@e75a11 scala> calc.add(1, 2) res1: Int = 3 scala> calc.brand res2: String = "HP" ~~~ 上面的例子展示了如何在類中用def定義方法和用val定義字段值。方法就是可以訪問類的狀態的函數。 ### 構造函數 構造函數不是特殊的方法,他們是除了類的方法定義之外的代碼。讓我們擴展計算器的例子,增加一個構造函數參數,并用它來初始化內部狀態。 ~~~ class Calculator(brand: String) { /** * A constructor. */ val color: String = if (brand == "TI") { "blue" } else if (brand == "HP") { "black" } else { "white" } // An instance method. def add(m: Int, n: Int): Int = m + n } ~~~ 注意兩種不同風格的評論。 你可以使用構造函數來構造一個實例: ~~~ scala> val calc = new Calculator("HP") calc: Calculator = Calculator@1e64cc4d scala> calc.color res0: String = black ~~~ ### 表達式 上文的Calculator例子說明了Scala是如何面向表達式的。顏色的值就是綁定在一個if/else表達式上的。Scala是高度面向表達式的:大多數東西都是表達式而非指令。 ### 旁白: 函數 vs 方法 函數和方法在很大程度上是可以互換的。由于函數和方法是如此的相似,你可能都不知道你調用的*東西*是一個函數還是一個方法。而當真正碰到的方法和函數之間的差異的時候,你可能會感到困惑。 ~~~ scala> class C { | var acc = 0 | def minc = { acc += 1 } | val finc = { () => acc += 1 } | } defined class C scala> val c = new C c: C = C@1af1bd6 scala> c.minc // calls c.minc() scala> c.finc // returns the function as a value: res2: () => Unit = <function0> ~~~ 當你可以調用一個不帶括號的“函數”,但是對另一個卻必須加上括號的時候,你可能會想*哎呀,我還以為自己知道Scala是怎么工作的呢。也許他們有時需要括號?*你可能以為自己用的是函數,但實際使用的是方法。 在實踐中,即使不理解方法和函數上的區別,你也可以用Scala做偉大的事情。如果你是Scala新手,而且在讀[兩者的差異解釋](https://www.google.com/search?q=difference+scala+function+method),你可能會跟不上。不過這并不意味著你在使用Scala上有麻煩。它只是意味著函數和方法之間的差異是很微妙的,只有深入語言內部才能清楚理解它。 ## 繼承 ~~~ class ScientificCalculator(brand: String) extends Calculator(brand) { def log(m: Double, base: Double) = math.log(m) / math.log(base) } ~~~ **參考**?Effective Scala 指出如果子類與父類實際上沒有區別,[類型別名](http://twitter.github.com/effectivescala/#Types%20and%20Generics-Type%20aliases)是優于`繼承`的。A Tour of Scala 詳細介紹了[子類化](http://www.scala-lang.org/node/125)。 ### 重載方法 ~~~ class EvenMoreScientificCalculator(brand: String) extends ScientificCalculator(brand) { def log(m: Int): Double = log(m, math.exp(1)) } ~~~ ### 抽象類 你可以定義一個*抽象類*,它定義了一些方法但沒有實現它們。取而代之是由擴展抽象類的子類定義這些方法。你不能創建抽象類的實例。 ~~~ scala> abstract class Shape { | def getArea():Int // subclass should define this | } defined class Shape scala> class Circle(r: Int) extends Shape { | def getArea():Int = { r * r * 3 } | } defined class Circle scala> val s = new Shape <console>:8: error: class Shape is abstract; cannot be instantiated val s = new Shape ^ scala> val c = new Circle(2) c: Circle = Circle@65c0035b ~~~ ## 特質(Traits) `特質`是一些字段和行為的集合,可以擴展或混入(mixin)你的類中。 ~~~ trait Car { val brand: String } trait Shiny { val shineRefraction: Int } ~~~ ~~~ class BMW extends Car { val brand = "BMW" } ~~~ 通過`with`關鍵字,一個類可以擴展多個特質: ~~~ class BMW extends Car with Shiny { val brand = "BMW" val shineRefraction = 12 } ~~~ **參考**?Effective Scala 對[特質的觀點](http://twitter.github.com/effectivescala/#Object oriented programming-Traits)。 **什么時候應該使用特質而不是抽象類?**?如果你想定義一個類似接口的類型,你可能會在特質和抽象類之間難以取舍。這兩種形式都可以讓你定義一個類型的一些行為,并要求繼承者定義一些其他行為。一些經驗法則: * 優先使用特質。一個類擴展多個特質是很方便的,但卻只能擴展一個抽象類。 * 如果你需要構造函數參數,使用抽象類。因為抽象類可以定義帶參數的構造函數,而特質不行。例如,你不能說`trait t(i: Int) {}`,參數`i`是非法的。 你不是問這個問題的第一人。可以查看更全面的答案:?[stackoverflow: Scala特質 vs 抽象類](http://stackoverflow.com/questions/1991042/scala-traits-vs-abstract-classes)?,?[抽象類和特質的區別](http://stackoverflow.com/questions/2005681/difference-between-abstract-class-and-trait), and?[Scala編程: 用特質,還是不用特質?](http://www.artima.com/pins1ed/traits.html#12.7) ## 類型 此前,我們定義了一個函數的參數為`Int`,表示輸入是一個數字類型。其實函數也可以是泛型的,來適用于所有類型。當這種情況發生時,你會看到用方括號語法引入的類型參數。下面的例子展示了一個使用泛型鍵和值的緩存。 ~~~ trait Cache[K, V] { def get(key: K): V def put(key: K, value: V) def delete(key: K) } ~~~ 方法也可以引入類型參數。 ~~~ def remove[K](key: K) ~~~ Built at?[@twitter](http://twitter.com/twitter)?by?[@stevej](http://twitter.com/stevej),?[@marius](http://twitter.com/marius), and?[@lahosken](http://twitter.com/lahosken)?with much help from?[@evanm](http://twitter.com/evanm),?[@sprsquish](http://twitter.com/sprsquish),?[@kevino](http://twitter.com/kevino),?[@zuercher](http://twitter.com/zuercher),?[@timtrueman](http://twitter.com/timtrueman),?[@wickman](http://twitter.com/wickman), and[@mccv](http://twitter.com/mccv); Russian translation by?[appigram](https://github.com/appigram); Chinese simple translation by?[jasonqu](https://github.com/jasonqu); Korean translation by?[enshahar](https://github.com/enshahar);
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看