Нужно ли импортировать неявный метод преобразования в объект-компаньон? Противоречие со Scala для нетерпеливой книги

Приведенный ниже код не работает, но он должен работать в соответствии с книгой "Scala для нетерпеливых" (см. отрывок ниже). Так что я тут не понимаю? Изменились ли правила неявного преобразования в последних версиях Scala (2.8 по сравнению с 2.10)?

РЕДАКТИРОВАТЬ:

Посмотрев на этот вопрос, я понял, что b.hello нужно изменить на (b:A).hello. Это не очень подразумевается. Есть ли способ обойти это?

РЕДАКТИРОВАТЬ 2:

После прочтения еще нескольких этого кажется, что нет другого пути, кроме импорта.

object A {
  implicit def b2a(b:B)=new A
}
class A{
  def hello=println("hello")
}
class B 

object ImplicitConversion extends App{
  val b=new B
  b.hello
}

введите здесь описание изображения


person jhegedus    schedule 07.03.2014    source источник
comment
Это может быть связано с тем, что вам не хватает возвращаемого типа неявного. implicit def b2a(b:B): A =new A   -  person flavian    schedule 07.03.2014


Ответы (2)


Это потому, что компилятор Scala не может понять, что вы хотите преобразовать B в A, просто взглянув на этот фрагмент кода:

val b = new B
b.hello // I know the source type is B, but what's the target type?

Рассмотрим случай, когда есть C, похожий на ваш A. Какое из двух преобразований следует выбрать Scala? Слишком много просить Scala искать все другие объекты-компаньоны в системе на предмет возможного неявного преобразования из уже известного исходного типа. И вполне возможно, что это закончится неоднозначным результатом.

Самое простое решение в вашем случае — переместить преобразование B в A из объекта-компаньона A в объект-компаньон B.

class A {
  def hello=println("hello")
}

class B 

object B {
  implicit def b2a(b:B)=new A
}

object ImplicitConversion extends App {
  val b=new B
  b.hello
}
person Ionuț G. Stan    schedule 07.03.2014

Решение, предложенное Стэном, удовлетворительно, потому что:

object B  {
  implicit def b2a(b:B)=new A 
}

class A{
  def hello=println("hello")
}

class B 

class C extends B


object ImplicitConversion extends App{

  val c=new C
  c.hello

}

Здесь мне нужно только включить неявное преобразование b2a в объект-компаньон B.

Затем я могу использовать все подклассы B как A.

person jhegedus    schedule 07.03.2014