隐式尺度是隐式的
Scala implicit implicit
我想在我的代码中做一些隐含的魔法,但问题很简单,我已经把它提取出来了。这似乎有点奇怪,因为根据我的阅读,以下内容应该有效。
implicit class Foo(value: Double) {
def twice = 2*value
}
2.0.twice
implicit def strToDouble(x: String) = Try(x.toDouble) match {
case Success(d) => d
case Failure(_) => 0.0
}
strToDouble("2.0").twice
val a: Double = "2.0"
val b: Double = "equals 0.0"
"2.0".twice
我遇到编译错误
value twice is not a member of String
[error] "2.0".twice
我得到你的编译器,两次是为 Double
s 定义的,而不是 String
s。但我确实告诉过你如何从 String
s 到 Double
s,这里没有歧义(据我所知),所以你不应该注意到 "2.0".twice
可以通过 strToDouble("2.0").twice
?
来完成
我是不是漏掉了什么?或者这是一种优化,以便编译器不会尝试 implicits
的所有可能排列(这将以超指数方式增长,我认为是阶乘)。我想我真的在寻找对此的确认或拒绝。
谢谢
如果你希望扩展方法在隐式转换后仍然适用,你可以修正隐式的定义class
implicit class Foo[A](value: A)(implicit ev: A => Double) {
def twice: Double = 2 * value
}
implicit def strToDouble(x: String): Double = ???
2.0.twice //compiles
"2.0".twice //compiles
I get you compiler, twice
is defined for Double
s, not String
s. But I
did tell you how to go from String
s to Double
s, and there is no
ambiguity here (as far as I can tell), so shouldn't you be able to
note that "2.0".twice
can be done by doing strToDouble("2.0").twice
?
根据规范,隐式转换仅适用于三种情况
https://scala-lang.org/files/archive/spec/2.13/07-implicits.html#views
2.0.twice
到Foo(2.0).twice
的转换是第二种情况,"2.0"
到strToDouble("2.0")
的转换是第一种情况。如您所见,没有项目可以将它们一起应用。因此,如果您希望它们一起适用,您应该像我上面显示的那样明确指定。
同样,如果您定义了从 A
到 B
和从 B
到 C
的转换,这并不意味着您有从 A
的转换至 C
case class A(i: Int)
case class B(i: Int)
case class C(i: Int)
implicit def aToB(a: A): B = B(a.i)
implicit def bToC(b: B): C = C(b.i)
A(1): B // compiles
B(1): C // compiles
// A(1): C //doesn't compile
我想在我的代码中做一些隐含的魔法,但问题很简单,我已经把它提取出来了。这似乎有点奇怪,因为根据我的阅读,以下内容应该有效。
implicit class Foo(value: Double) {
def twice = 2*value
}
2.0.twice
implicit def strToDouble(x: String) = Try(x.toDouble) match {
case Success(d) => d
case Failure(_) => 0.0
}
strToDouble("2.0").twice
val a: Double = "2.0"
val b: Double = "equals 0.0"
"2.0".twice
我遇到编译错误
value twice is not a member of String
[error] "2.0".twice
我得到你的编译器,两次是为 Double
s 定义的,而不是 String
s。但我确实告诉过你如何从 String
s 到 Double
s,这里没有歧义(据我所知),所以你不应该注意到 "2.0".twice
可以通过 strToDouble("2.0").twice
?
我是不是漏掉了什么?或者这是一种优化,以便编译器不会尝试 implicits
的所有可能排列(这将以超指数方式增长,我认为是阶乘)。我想我真的在寻找对此的确认或拒绝。
谢谢
如果你希望扩展方法在隐式转换后仍然适用,你可以修正隐式的定义class
implicit class Foo[A](value: A)(implicit ev: A => Double) {
def twice: Double = 2 * value
}
implicit def strToDouble(x: String): Double = ???
2.0.twice //compiles
"2.0".twice //compiles
I get you compiler,
twice
is defined forDouble
s, notString
s. But I did tell you how to go fromString
s toDouble
s, and there is no ambiguity here (as far as I can tell), so shouldn't you be able to note that"2.0".twice
can be done by doingstrToDouble("2.0").twice
?
根据规范,隐式转换仅适用于三种情况
https://scala-lang.org/files/archive/spec/2.13/07-implicits.html#views
2.0.twice
到Foo(2.0).twice
的转换是第二种情况,"2.0"
到strToDouble("2.0")
的转换是第一种情况。如您所见,没有项目可以将它们一起应用。因此,如果您希望它们一起适用,您应该像我上面显示的那样明确指定。
同样,如果您定义了从 A
到 B
和从 B
到 C
的转换,这并不意味着您有从 A
的转换至 C
case class A(i: Int)
case class B(i: Int)
case class C(i: Int)
implicit def aToB(a: A): B = B(a.i)
implicit def bToC(b: B): C = C(b.i)
A(1): B // compiles
B(1): C // compiles
// A(1): C //doesn't compile