У меня есть два неявных преобразования, которые добавляют метод 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 ответа
Если проблема заключается в существовании неявного внутри Predef
, вы должны отключить Predef
импорт, как описано здесь: Переопределить неявные преобразования Predef
В качестве примера, давайте попробуем создать новую функцию 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
после жалоб компилятора на неоднозначные преобразования.
Вы должны включить оба 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
в функцию.
Как это работает в вашем примере:
- Компилятор видит вызов
foo(1)
. - Он заменяет его на
foo.apply(1)
. - Выясняется, что класс
Foo
не имеет методаapply
и пытается найти неявное преобразование в класс с помощью этого метода. - Он находит два преобразования,
f1
иf2
, и отказывается от него.
Похожие вопросы
Новые вопросы
scala
Scala - это язык программирования общего назначения, в основном предназначенный для виртуальной машины Java. Разработанный для краткого, элегантного и безопасного для типов представления общих шаблонов программирования, он сочетает в себе как императивный, так и функциональный стили программирования. Его ключевые особенности: продвинутая система статического типа с выводом типа; типы функций; сопоставления с образцом ; неявные параметры и преобразования; перегрузка оператора; полная совместимость с Java; совпадение