Scala基礎:閉包、柯里化、隱式轉換和隱式引數
阿新 • • 發佈:2018-11-11
閉包,和js中的閉包一樣,返回值依賴於宣告在函式外部的一個或多個變數,那麼這個函式就是閉包函式。
val i: Int = 20 //函式func的方法體中使用了在func外部定義的變數 那func就是個閉包函式 val func = (x: Int) => x + i
柯里化(Currying)指的是把原來接受多個引數的函式變換成接受一個引數的函式過程,並且返回接受餘下的引數且返回結果為一個新函式的技術。柯里化並不是scala特有的,js中也有。
package com.zy.scala object CurryingDemo { def main(args: Array[String]): Unit= { //原本的方法 def m(x: Int, y: Int) = x + y //第一種柯里化 def first(x: Int) = (y: Int) => x + y val second = first(1) val result: Int = second(2) println(result) //第二種柯里化 def curriedSum(x: Int)(y: Int) = x + y val sum: Int = curriedSum(1)(2) println(sum) } }
Scala 提供的隱式轉換和隱式引數功能,是非常有特色的功能。是 Java 等程式語言所沒有的功能。它可以允許你手動指定,將某種型別的物件轉換成其他型別的物件或者是給一個類增加方法。通過這些功能,
可以實現非常強大、特殊的功能。 Scala 的隱式轉換,其實最核心的就是定義隱式轉換方法,即 implicit conversion function。定義的隱式轉換方法,只要在編寫的程式內引入,就會被Scala 自動使用。Scala 會根據隱式轉換方法的簽名,
在程式中使用到隱式轉換方法接收的引數型別定義的物件時,會自動將其傳入隱式轉換方法,轉換為另外一種型別的物件並返回。這就是“隱式轉換”。其中所有的隱式值和隱式方法必須放到 object 中。 然而使用 Scala 的隱式轉換是有一定的限制的,總結如下: implicit 關鍵字只能用來修飾方法、變數(引數)。 隱式轉換的方法在當前範圍內才有效。如果隱式轉換不在當前範圍內定義(比如定義在另一個類中或包含在某個物件中),那麼必須通過import 語句將其導。 所謂的隱式引數,指的是在函式或者方法中,定義一個用 implicit 修飾的引數,此時 Scala 會嘗試找到一個指定型別的,用 implicit 修飾的引數,即隱式值,並注入引數。 Scala 會在兩個範圍內查詢: 當前作用域內可見的 val 或 var 定義的隱式變數; 一種是隱式引數型別的伴生物件內的隱式值;
隱式引數案例
package com.zy.scala object Company { //在 object 中定義隱式值 注意:同一型別的隱式值只允許出現一次,否則會報錯 implicit val aaa = "zhangsan" implicit val bbb = 10000.00 } class Boss { //注意引數匹配的型別 它需要的是 String 型別的隱式值 def callName()(implicit name: String): String = { name + " is coming !" } //定義一個用 implicit 修飾的引數 //注意引數匹配的型別 它需要的是 Double 型別的隱式值 def getMoney()(implicit money: Double): String = { " 當月薪水:" + money } } object Boss extends App { //使用 import 匯入定義好的隱式值,注意:必須先載入否則會報錯 import Company._ val boss = new Boss println(boss.callName() + boss.getMoney()) }
隱式轉換
package com.zy.scala import java.io.File import scala.io.Source object MyPredef { //定義隱式轉換方法 implicit def file2RichFile(file: File) = new RichFile(file) } class RichFile(val f: File) { def read() = Source.fromFile(f).mkString } object RichFile { def main(args: Array[String]) { val f = new File("E://words.txt") //使用 import 匯入隱式轉換方法 import MyPredef._ //通過隱式轉換,讓 File 類具備了 RichFile 類中的方法 val content = f.read() println(content) } }
package com.zy.scala class Man(val name: String) class SuperMan(val name: String) { def heat = print("超人打怪獸") } object SuperMan { //隱式轉換方法 implicit def man2SuperMan(man: Man) = new SuperMan(man.name) def main(args: Array[String]) { val hero = new Man("hero") //Man 具備了 SuperMan 的方法 hero.heat } }
package com.zy.scala class A(c: C) { def readBook(): Unit = { println("A 說:好書好書...") } } class B(c: C) { def readBook(): Unit = { println("B 說:看不懂...") } def writeBook(): Unit = { println("B 說:不會寫...") } } class C object AB { //建立一個類的 2 個類的隱式轉換 implicit def C2A(c: C) = new A(c) implicit def C2B(c: C) = new B(c) } object B { def main(args: Array[String]) { //導包 //1. import AB._ 會將 AB 類下的所有隱式轉換導進來 //2. import AB._C2A 只匯入 C 類到 A 類的的隱式轉換方法 //3. import AB._C2B 只匯入 C 類到 B 類的的隱式轉換方法 import AB._ val c = new C //由於 A 類與 B 類中都有 readBook(),只能匯入其中一個,否則呼叫共同方法時程式碼報錯 //c.readBook() //C 類可以執行 B 類中的 writeBook() c.writeBook() } }