Scala隐式隐式

问题描述

我正在尝试在代码中做一些隐式魔术,但是问题非常简单,我在这里已将其提取出来。从我阅读的内容来看,以下内容应该可以工作,这似乎有点奇怪。

   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(而非String)定义了两次。但是我确实告诉过您如何从StringDouble s,而且这里没有歧义(据我所知),所以您不应该注意到{{ 1}}可以通过"2.0".twice完成吗?

我在这里想念什么吗?还是这是一种优化,以便编译器不会尝试strToDouble("2.0").twice的所有可能排列(我认为它会成指数增长)。我想我实际上是在寻求确认或拒绝。

谢谢

解决方法

如果希望扩展方法即使在隐式转换后仍然适用,则可以修复隐式类的定义

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

我为您提供了编译器,twice是为Double而不是String定义的。但是我 确实告诉您如何从StringDouble s,而且没有 据我所知,这里的模棱两可,所以你不应该 请注意,"2.0".twice可以通过strToDouble("2.0").twice完成吗?

根据规范,隐式转换仅在三种情况下适用

Why can't the compiler select the correct String.contains method when using this lambda shorthand?

https://scala-lang.org/files/archive/spec/2.13/07-implicits.html#views

2.0.twiceFoo(2.0).twice的转换是第二种情况,而从"2.0"strToDouble("2.0")的转换是第一种情况。如您所见,没有项目可以将它们一起应用。因此,如果您希望它们一起适用,则应像我上面显示的那样明确指定。

类似地,如果您定义了从AB以及从BC的转化,这并不意味着您已经从A到{ {1}}

C

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...