Как переопределить неявное значение?

Предположим, у меня есть код:

class A(implicit s:String = "foo"){println(s)}

object X {
   implicit val s1 = "hello"
}
object Y {
   import X._
   // do something with X
   implicit val s2 = "hi"
   val a = new A
}

Я получаю сообщение об ошибке:

<console>:14: error: ambiguous implicit values:
 both value s2 in object Y of type => String
 and value s1 in object X of type => String
 match expected type String
           val a = new A

Могу ли я каким-либо образом указать Scala использовать значение s2 в Y? (если я переименую s2 в s1, он будет работать как положено, но это не то, что мне нужно).

Другое решение — не делать import X._, чего я снова пытаюсь избежать.


person Jus12    schedule 28.02.2015    source источник


Ответы (3)


Еще вы можете импортировать все, кроме s1: import X.{s1 => _, _}.

person Alexey Romanov    schedule 28.02.2015
comment
Спасибо за ответ! Пожалуй, лучший на данный момент. - person Jus12; 28.02.2015

Я согласен с другим ответом, что явное предоставление неявного в таких ситуациях предпочтительнее, но если вы настаиваете на том, чтобы «понизить» другое неявное, чтобы оно больше не рассматривалось как неявное, тогда это действительно возможно:

class A(implicit s:String = "foo"){println(s)}

object X {
  implicit val s1 = "hello"
}
object Y {
  import X._
  val s1 = X.s1 //downgrade to non-implicit

  // do something with X
  implicit val s2 = "hi"
  val a = new A
}

Опять же, это немного хакерски, но это работает.

person cmbaxter    schedule 28.02.2015
comment
Согласен .. Немного хакерский, но делает свою работу. - person Jus12; 28.02.2015

Пытаться:

new A()(s2)

Это должно переопределить неявный параметр путем его явного указания.

person Others    schedule 28.02.2015
comment
Это противоречит цели использования неявного параметра. У меня есть new A в нескольких местах, и тогда я бы предпочел просто удалить неявное. - person Jus12; 28.02.2015
comment
@ Jus12 Jus12 Я просто не понимаю, как вы сможете сохранить импорт подстановочных знаков и не переопределить явный хотя бы один раз ... - person Others; 28.02.2015
comment
Использование implicit для чего-то небольшого и объективного, такого как strings, в первую очередь не имеет смысла. - person sarveshseri; 28.02.2015
comment
@SarveshKumarSingh Я согласен. Строка просто для примера. В моем реальном коде это довольно сложный объект. - person Jus12; 28.02.2015
comment
@ Jus12 Что произойдет, если вы назовете s2 так же, как s1? Просто из любопытства - person Others; 28.02.2015
comment
И у вас есть несколько экземпляров этого сложного объекта в области видимости. Implicits обычно имеют смысл для Helper-functions, typeclass abstract evidences, таких как Monads или больших, и предназначены для повторного использования больших объектов, таких как ActorSystem. - person sarveshseri; 28.02.2015
comment
@Others: Когда я использую s1, поведение соответствует тому, что я хочу и ожидал: оно переопределяет старое. Однако я не хочу, чтобы имена были одинаковыми по другим причинам. - person Jus12; 28.02.2015