Почему неявные члены объекта пакета в некоторых случаях видимы для подпакета?
Давайте рассмотрим следующую иерархию пакетов:
test
--foo
--Foo.scala
--bar
--Bar.scala
package.scala
Если у вас есть следующий код в объекте пакета test
:
package object test {
implicit class Pipe[A](a: A) {
def |>[B](f: A => B): B = f(a)
}
}
Затем кейс-класс в Foo.scala (в пакете test.foo
):
package test.foo
case class Foo(i: Int)
object Foo {
2.0 |> math.floor // 1 - Does not compile, package object is not visible
}
И, наконец, приложение в упаковке test.bar
:
package test.bar
import test.foo.Foo
object Bar extends App {
def plus2(i: Int) = i + 2
def plus2(f: Foo) = f.i + 2
def plus2(o: Option[Foo]) = o.map(f => Foo(f.i + 2))
println(2 |> plus2) // 2 - Does not compile, package object is not visible
println(Foo(2) |> plus2) // 3 - Does compile !?
println(Option(Foo(2)) |> plus2) // 4 - Does compile too !?
}
Первые два комментария показывают нам строки, которые не компилируются, что является ожидаемым поведением, поскольку объект пакета не виден ни в одном подпакете.
Почему третий и четвертый случаи компилируются? Почему в этих случаях применяется неявное преобразование? Мы не используем класс корневого пакета (Foo находится в подпакете, а Option вообще отсутствует в пакете), а также мы не импортируем корневой пакет.
1 ответ
Это вызвано тем, когда последствия, определенные в package object
эти последствия будут работать только для типа с префиксом этого пакета. для вашего примера это тип Foo
,
так что для вашей проблемы вы можете вручную импортировать последствия, такие как:
import test._
println(2 |> plus2)
println(Foo(2) |> plus2)
Найти еще:
Обратите внимание, что пакеты внутренне представлены как классы с сопутствующими модулями для хранения членов пакета. Таким образом, имплициты, определенные в объекте пакета, являются частью неявной области видимости типа с префиксом этого пакета.
http://www.scala-lang.org/files/archive/spec/2.12/07-implicits.html