Когда неявный объект импортируется из объекта-компаньона?
Я знаю, что это уже сотый вопрос о имплицитах / сопутствующих объектах. Однако я нигде не нашел этот случай.
В "Tryout", почему A не требуется импорт для неявного класса, а B это нужно? Thankx.
class LongConsumer {
def consume(l: Long) = Unit
}
case class X(x: Long)
object X extends (Long => X) {
implicit class ConsumeX(val c: LongConsumer) extends AnyVal {
def consume(x: X) = c consume x.x
}
implicit class EatX(val c: LongConsumer) extends AnyVal {
def eat(x: X) = c consume x.x
}
}
object Tryout {
// A: does not need import to compile - why?
new LongConsumer().consume(X(10L))
// B: needs import to compile - why?
import X.EatX
new LongConsumer().eat(X(10L))
}
1 ответ
Есть только три случая для просмотра.
http://www.scala-lang.org/files/archive/spec/2.11/07-implicit-parameters-and-views.html
Ваш случай A является № 1, где X не является длинным, как ожидается от потребления. (Изменить: Извините, я смотрю Hulu. Это № 3, где потребление не применяется. Конвертация из LongConsumer в ConsumeX. В этом случае я бы не ожидал, что неявная область действия X будет в игре.)
Но обратите внимание, что неявная область действия - это область действия X => Long.
Область действия Function[X, Long] включает область действия обоих параметров типа, а область действия X включает сопутствующий элемент X. (В предыдущем разделе 7.2 перечислено, что находится в неявной области действия.) Интуиция заключается в том, что у вас есть один тип в руке, но нужен другой; любой тип может обеспечить преобразование.
В вашем случае B это дело № 2, а объем LongConsumer не обеспечивает преобразование.
Я попросил ОД для разъяснения. -Ytyper-debug
говорит, что это вторая попытка.
| | second try: (l: Long)Unit.type and eatery.X.type
| | |-- eatery.X.type EXPRmode (silent: value <local Tryout> in Tryout)
| | | |-- X.apply BYVALmode-EXPRmode-FUNmode-POLYmode (silent: value <local Tryout> in Tryout)
| | | | \-> (x: Long)eatery.X
| | | \-> eatery.X
| | |-- eatery.this.X.ConsumeX BYVALmode-EXPRmode-FUNmode-POLYmode (silent: value <local Tryout> in Tryout) implicits disabled
| | | \-> eatery.X.ConsumeX.type <and> (c: eatery.LongConsumer)eatery.X.ConsumeX
| | |-- (c: eatery.LongConsumer)eatery.X.ConsumeX EXPRmode-POLYmode-QUALmode (site: value <local Tryout> in Tryout)
| | | \-> eatery.X.ConsumeX
| | |-- eatery.this.X.ConsumeX(new LongConsumer()).consume BYVALmode-EXPRmode-FUNmode-POLYmode (silent: value <local Tryout> in Tryout)
| | | \-> (x: eatery.X)Unit.type (with underlying type (x: eatery.X)Unit.type)
| | \-> Unit.type
| \-> [object Tryout] eatery.Tryout.type
Результаты в:
https://issues.scala-lang.org/browse/SI-5089
@retronym говорит: более широкий вопрос о том, почему неявная область действия включает компаньонов типов аргументов приложений, известен как "проблема 1 + BigInteger(1)"
Видно, когда вы так говорите.
Также см. Здесь описание ссылки в разделе "Неявная область действия типа аргумента".