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:
An implicit conversion from type S to type T is defined by an implicit value which has function type S => T, or by an implicit method convertible to a value of that type.
所以,你应该有 一个 隐式方法将 Foo
转换为函数。
在您的示例中它是如何工作的:
- 编译器发现
foo(1)
调用。
- 替换为
foo.apply(1)
。
- 发现 class
Foo
没有方法 apply
并尝试使用此方法找到到 class 的隐式转换。
- 它找到了两个转换,
f1
和 f2
,并放弃了它。
如果问题出在 Predef
中存在的隐含问题,您应该禁用 Predef
导入,如下所述:Override Predef's implicit conversions
例如,让我们尝试为 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)
^
所以,我们应该禁用 augmentString
从 Predef
导入:
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.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
您可以对来自 class Foo
的隐式转换执行相同的操作,因为编译器会抱怨转换不明确。
我有两个添加 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:
An implicit conversion from type S to type T is defined by an implicit value which has function type S => T, or by an implicit method convertible to a value of that type.
所以,你应该有 一个 隐式方法将 Foo
转换为函数。
在您的示例中它是如何工作的:
- 编译器发现
foo(1)
调用。 - 替换为
foo.apply(1)
。 - 发现 class
Foo
没有方法apply
并尝试使用此方法找到到 class 的隐式转换。 - 它找到了两个转换,
f1
和f2
,并放弃了它。
如果问题出在 Predef
中存在的隐含问题,您应该禁用 Predef
导入,如下所述:Override Predef's implicit conversions
例如,让我们尝试为 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)
^
所以,我们应该禁用 augmentString
从 Predef
导入:
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.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
您可以对来自 class Foo
的隐式转换执行相同的操作,因为编译器会抱怨转换不明确。