編譯器可以自動插入 implicit 的最后一個用法是隱含參數(shù)。 比如編譯器在需要是可以把 someCall(a)修改為 someCall(a)(b)或者 new someClass(a) 修改為 new SomeClass(a)(b),也就是說編譯器在需要的時候會自動補充缺少的參數(shù)來完成方法的調(diào)用。其中(b)為一組參數(shù),而不僅僅只最后一個參數(shù)。
這里我們給出一個簡單的例子:假定你定義了一個類 PreferredPrompt,其中定義了一個用戶選擇的命令行提示符(比如”$ “或者”> “)。
class PreferredPrompt(val preference:String)
另外又定義了一個 Greeter 對象,該對象定義了一個 greet 方法,該方法定義了兩個參數(shù),第一個參數(shù)代表用戶姓名,第二個參數(shù)類型為 P referredPrompt,代表提示符。
object Greeter{
def greet(name:String)(implicit prompt: PreferredPrompt) {
println("Welcome, " + name + ". The System is ready.")
println(prompt.preference)
}
}
第二個參數(shù)標記為 implicit,表明允許編譯器根據(jù)需要自動添加。 我們首先采用一般方法的調(diào)用方法,提供所有的參數(shù):
scala> val bobsPrompt =new PreferredPrompt("relax> ")
bobsPrompt: PreferredPrompt = PreferredPrompt@7e68a062
scala> Greeter.greet("Bob")(bobsPrompt)
Welcome, Bob. The System is ready.
relax>
這種用法和我們不給第二個參數(shù)添加 implicit 調(diào)用時一樣的結(jié)果。前面我們提過,隱含參數(shù)的用法有點類似某些 Dependency Injection 框架。 比如我們在某些地方定義一個 PreferredPrompt 對象,而希望編譯器在需要時注入該對象,那么該如果使用呢。
首先,我們定義一個對象,然后在該對象中定義一個 PreferredPrompt 類型的隱含實例:
object JamesPrefs{
implicit val prompt=new PreferredPrompt("Yes, master> ")
}
然后我們只提供第二個參數(shù)看看什么情況:
scala> Greeter.greet("James")
<console>:10: error: could not find implicit value for parameter prompt: PreferredPrompt
Greeter.greet("James")
^
出錯了,這是因為編譯器在當前作用域找不到 PreferredPrompt 類型的隱含變量,它定義在對象 JamesPrefs 中,因此需要使用 Import 引入:
scala> import JamesPrefs._
import JamesPrefs._
scala> Greeter.greet("James")
Welcome, James. The System is ready.
Yes, master>
可以看到編譯器自動插入了第二個參數(shù),要注意的是,implicit 關(guān)鍵字作用到整個參數(shù)列表,我們修改一下上面的例子看看:
class PreferredPrompt(val preference:String)
class PreferredDrink(val preference:String)
object Greeter{
def greet(name:String)(implicit prompt: PreferredPrompt, drink:PreferredDrink) {
println("Welcome, " + name + ". The System is ready.")
print("But while you work,")
println("why not enjoy a cup of " + drink.preference + "?")
println(prompt.preference)
}
}
object JamesPrefs{
implicit val prompt=new PreferredPrompt("Yes, master> ")
implicit val drink=new PreferredDrink("coffee")
}
import JamesPrefs._
Greeter.greet("James")
scala> Greeter.greet("James")
Welcome, James. The System is ready.
But while you work,why not enjoy a cup of coffee?
Yes, master>
這里有一點要注意的是,這里 implicit 參數(shù)的類型我們沒有直接使用 String 類型,事實我們可以使用 String 類型:
object Greeter{
def greet(name:String)(implicit prompt: String) {
println("Welcome, " + name + ". The System is ready.")
println(prompt)
}
}
implicit val prompt="Yes, master> "
Greeter.greet("James")
scala> Greeter.greet("James")
Welcome, James. The System is ready.
Yes, master>
當問題是如果有多個參數(shù)都使用 implicit 類型,而類型相同,你就無法提供多個參數(shù),因此 implicit 類型的參數(shù)一般都是定義特殊的類型。