Scala通过参数数量隐式def解析

时间:2017-04-24 10:01:40

标签: scala implicit-conversion

我有两个隐式转换添加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

如果明确应该使用哪一个,为什么会抱怨?

2 个答案:

答案 0 :(得分:3)

您应该将apply()implicit def f1(foo: Foo) = new { def apply(x: Int) = ??? def apply(x: Int, y: Int) = ??? } 包括在一个隐含的内容中:

Foo

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

  

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

因此,您应该完全一个隐式方法将foo(1)转换为函数。

在您的示例案例中如何运作:

  1. 编译器会看到foo.apply(1)调用。
  2. 将其替换为Foo
  3. 它发现,班级apply没有方法f1,并尝试使用此方法找到隐式转化为类。
  4. 它发现了两次转化,f2Recycler view particular item swap ViewInteraction recyclerView = onView(allOf(withId(R.id.rc_vehicle_list), withParent(withId(R.id.ll_vehicle)), isDisplayed())); recyclerView.perform(actionOnItemAtPosition(3,swipeUp())); public static ViewAction swipeUp() { return new GeneralSwipeAction(Swipe.FAST, GeneralLocation.CENTER_LEFT, GeneralLocation.CENTER_RIGHT, Press.FINGER); } ,并放弃了它。

答案 1 :(得分:1)

如果问题出现在现有隐式内部Predef中,您应该停用Predef导入,如下所述:Override Predef's implicit conversions

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

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$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的隐式转化,您可以执行相同的操作,因为编译器会抱怨有关转换的信号。