就是在當某物件沒有要呼叫的方法時,可以定義 implicit function 編譯器會嘗試使用 implicit function 來呼叫,將原物件轉換成另一個物件.
由於 Int 沒有 append 方法所以下面執行會失敗 :
scala> 1 append 2
<console>:13: error: value append is not a member of Int
1 append 2
^
定義一個 MyAppend 及 append 方法 :
scala> class MyAppend(num: Int) {
| def append(newNum: Int) = num.toString + newNum.toString
| }
defined class MyAppend
在 REPL 直接寫 implicit 會出現 warning,但還是可以使用的 :
scala> implicit def intToMyAppend(x:Int) = new MyAppend(x)
<console>:13: warning: implicit conversion method intToMyAppend should be enabled
by making the implicit value scala.language.implicitConversions visible.
This can be achieved by adding the import clause 'import scala.language.implicitConversions'
or by setting the compiler option -language:implicitConversions.
See the Scaladoc for value scala.language.implicitConversions for a discussion
why the feature should be explicitly enabled.
implicit def intToMyAppend(x:Int) = new MyAppend(x)
^
intToMyAppend: (x: Int)MyAppend
如果不要有 warning 可以 import scala.language.implicitConversions :
scala> import scala.language.implicitConversions
import scala.language.implicitConversions
scala> implicit def intToMyAppend(x:Int) = new MyAppend(x)
intToMyAppend: (x: Int)MyAppend
加上 implicit 函式後,編譯器會在範圍內找到對應型態的 implicit 函式呼叫.所以會變成 intToMyAppend(1) append 2
scala> 1 append 2
res8: String = 12
也可以把 implicit 函式抽成一個 object.
寫一隻 MyAppend.scala 並 compiler :
class MyAppend(num: Int) {
def append(newNum: Int) = num.toString + newNum.toString
}
scalac MyAppend.scala
寫一隻 MyConvert.scala 並 compiler :
object MyConvert {
implicit def intToMyAppend(x:Int) = new MyAppend(x)
}
scalac MyConvert.scala
寫一隻 ConvertTest.scala,並將有定義隱含函式的 object(MyConvert) import 進來 :
import MyConvert._
object ConvertTest {
def main(args: Array[String]): Unit = {
val result = 1 + 2
println(result)
val res = 1 append 2
println(res)
}
}
接著執行 ConvertTest.scala :
daniel@Danielde-MacBook-Pro > scala ConvertTest.scala
3
12
在方法裡使用 implicit 物件,如果使用該方法時沒傳入物件,則會使用 implicit 物件傳入.
寫一隻 Employees.scala,並 compiler :
class Employees(name:String ,val amt:Int) {
def getName = name
}
object Employees {
import Employees._
implicit val employee: Employees = new Employees("Daniel",50)
def sayHello(implicit employee: Employees) = "Hello " + employee.getName
}
scalac Employees.scala
寫一隻 EmployeesTest.scala,sayHello 沒給參數的話,會帶隱含物件,所以會印出 Daniel.
object EmployeesTest {
def main(args: Array[String]): Unit = {
println(Employees.sayHello)//Hello Daniel
println(Employees.sayHello(new Employees("Sam",5000)))//Hello Sam
}
}
執行時,加上 classpath :
daniel@Danielde-MacBook-Pro > scala -cp "./" EmployeesTest.scala
Hello Daniel
Hello Sam