繁体   English   中英

Scala隐式def解析的参数数量

[英]Scala implicit def resolution by number of parameters

我有两个隐式转换,它们添加了apply方法。

implicit def f1(foo: Foo) = new {
  def apply(x: Int) = ???
}

implicit def f2(foo: Foo) = new {
  def apply(x: Int, y: Int) = ???
}

但是我不能使用它们,因为编译器抱怨模棱两可的隐式转换

foo(1) // compile error

如果清楚应该使用哪一个,为什么会抱怨呢?

您应该将两个apply()都包含在一个隐式中:

implicit def f1(foo: Foo) = new {
  def apply(x: Int) = ???
  def apply(x: Int, y: Int) = ???
}

http://docs.scala-lang.org/tutorials/tour/implicit-conversions

从类型S到类型T的隐式转换由具有函数类型S => T的隐式值定义,或由可转换为该类型的值的隐式方法定义。

因此,您应该只有一种Foo转换为函数的隐式方法。

在您的示例案例中它是如何工作的:

  1. 编译器看到foo(1)调用。
  2. 它将它替换为foo.apply(1)
  3. 结果发现,该类Foo没有apply方法,并尝试使用此方法查找对类的隐式转换。
  4. 它找到了两个转换f1f2 ,并放弃了。

如果问题出在Predef内部存在隐式问题,则应按如下所述禁用Predef导入: 覆盖Predef的隐式转换

例如,让我们尝试为String创建新的apply函数。

scala> implicit def stringToFunction(s: String) = new {
     |   def apply(x1: Int) = ???
     | }
stringToFunction: (s: String)AnyRef{def apply(x1: Int): Nothing}

scala> "123"(15)
<console>:13: error: type mismatch;
 found   : String("123")
 required: ?{def apply: ?}
Note that implicit conversions are not applicable because they are ambiguous:
 both method augmentString in object Predef of type (x: String)scala.collection.immutable.StringOps
 and method stringToFunction of type (s: String)AnyRef{def apply(x1: Int): Nothing}
 are possible conversion functions from String("123") to ?{def apply: ?}
       "123"(15)
       ^
<console>:13: error: String("123") does not take parameters
       "123"(15)
            ^

因此,我们应该禁用从Predef augmentString导入:

scala> import Predef.{augmentString => _, _}
import Predef.{augmentString=>_, _}

scala> "123"(15)
<console>:14: error: type mismatch;
 found   : String("123")
 required: ?{def apply: ?}
Note that implicit conversions are not applicable because they are ambiguous:
 both method wrapString in class LowPriorityImplicits of type (s: String)scala.collection.immutable.WrappedString
 and method stringToFunction of type (s: String)AnyRef{def apply(x1: Int): Nothing}
 are possible conversion functions from String("123") to ?{def apply: ?}
       "123"(15)
       ^
<console>:14: error: String("123") does not take parameters
       "123"(15)
            ^

让我们也禁用wrapString ,这将最终实现我们想要做的事情:

scala> import Predef.{augmentString => _, wrapString => _, _}
import Predef.{augmentString=>_, wrapString=>_, _}

scala> "123"(15)
scala.NotImplementedError: an implementation is missing
  at scala.Predef$.$qmark$qmark$qmark(Predef.scala:284)
  at $anon$1.apply(<console>:12)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.lang.reflect.Method.invoke(Method.java:498)
  ... 31 elided

在编译器抱怨模棱两可的转换之后,您可以对类Foo隐式转换执行相同的操作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM