我試圖通過使用implicit
類和類型類將輔助方法添加到配置庫。然而,我對Scala非常陌生(1周),並且一直無法找出爲什麼下面的代碼發出編譯錯誤(我在代碼註釋中提供了工作解決方案)在方法調用的方法中找不到隱式值
簡化第三方包:
package pkg
class Config {
def hasPath(path: String) = { false }
def getString(path: String) = { "str" }
def getInt(path: String) = { 7 }
def getDouble(path: String) = { 3.14d }
}
我的示例文件:
import pkg._
object Helpers {
trait Extractor[T] {
def extract(cfg: Config, path: String): T
}
object Extractor {
implicit object IntExtractor extends Extractor[Int] {
def extract(cfg: Config, path: String) = {
99
}
}
}
implicit class BetterConfig(cfg: Config) {
def extract[T](path: String)(implicit extractor: Extractor[T]): T = {
extractor.extract(cfg, path)
}
// This example works if I add the implicit parameter:
// (implicit extractor: Extractor[T])
def extract[T](path: String, default: T): T = {
if (cfg.hasPath(path)) {
extract[T](path)
// ^error here
} else {
default
}
}
}
}
object Demo extends App {
import Helpers._
val cfg = new Config
val x = cfg.extract("foo", 3)
println(s"x: ${x}")
}
此代碼提供了錯誤could not find implicit value for parameter extractor: Helpers.Extractor[T]
爲什麼不能IMPL從extract(path, default)
內撥打電話extract(path)
會發現icit值?我對範圍規則或解決隱含的理解是錯誤的。我會認爲,當extract(path)
的調用是在extract(path, default)
之內完成時,隱式仍然會從Extractor
的伴隨對象中解析出來。
我已經試過這與Scala 2.10.6和2.11.8。
編譯器在什麼時候嘗試確定T是什麼?我想我錯誤地認爲它會知道T是Int,因爲那是整數字面量'3'的類型。我完全可以看到String版本不起作用,因爲我沒有提供Extractor [String]的實現(至少在本例中)。 – Timma
當編譯器正在查看'def extract [T](path:String,default:T):T'時,它並不試圖弄清楚T是什麼:你的定義必須適用於_all_'T '。 –
在查看'cfg.extract(「foo」,3)'時,它指出'T'是'Int'用於這個特定的調用,但是這是獨立的;即使你從來沒有調用過這個方法,你在定義中已經有了一個錯誤。 –