Неявное преобразование применяется, когда предположительно эквивалентный неявный класс не - PullRequest
1 голос
/ 20 июня 2019

У меня есть довольно простой пример, когда одна функция foo(), которая принимает неявный аргумент типа A, пытается вызвать другую функцию bar(), которая принимает неявный аргумент типа B. В проекте, где я столкнулся с этим вопросом, B содержит подмножество функциональных возможностей A, поэтому я хотел бы обеспечить неявное преобразование из A в B для создания кейсов как в этом примере бесшовные.

Реализация этого с использованием неявного преобразования B.implicitConversion() работает как ожидалось. Следующий код принят scalac 2.13.0:

trait A

trait B

object B {
  // implicit class ImplicitClass(value: A) extends B

  implicit def implicitConversion(implicit se: A) = ???
}

class Test {
  def foo()(implicit a: A) = bar()

  def bar()(implicit b: B) = ???
}

Как ни странно, реализация преобразования с использованием неявного класса ImplicitClass не работает (удаляя определение implicitConversion() и добавляя определение ImplicitClass). Код отклонен scalac:

$ scalac 'Test.scala:12: error: could not find implicit value for parameter b: B
def foo()(implicit a: A) = bar()
^
one error found

Я бы предположил, что в такой ситуации неявные классы и неявное преобразование являются взаимозаменяемыми. Чего мне здесь не хватает, почему два способа предоставления конверсии не эквивалентны?

1 Ответ

2 голосов
/ 21 июня 2019

ImplicitClass эквивалентно

class ImplicitClass(value: A) extends B

implicit def ImplicitClass(value: A): ImplicitClass

Вы можете увидеть разницу: это неявное преобразование принимает value: A в качестве явного параметра, в отличие от вашего def implicitConversion. И если вы измените на

def foo()(implicit a: A) = bar()(a)

вы увидите, как это работает.

...