在方法调用的方法中找不到隐式值
问题描述:
我试图通过使用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。
答
您的来电需要一个隐含的Extractor[T]
,关于T
什么都不知道。它将从伴侣对象解析出来,如果有的话,但是那里没有这样的方法。
想象一下它的工作。然后
val cfg = new Config
val x = cfg.extract[String]("foo", "")
也应该编译。但是,如果没有隐含的Extractor[String]
任何地方它将如何工作?
编译器在什么时候尝试确定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'用于这个特定的调用,但是这是独立的;即使你从来没有调用过这个方法,你在定义中已经有了一个错误。 –