Consider
a function f
defined in package p1
a package p2
which does not contain p1
a package p3
which does not contain p2
or p1
nor it is contained by p2
or p1
.
In Scala, is it possible to declare that f
is accessible from package p2
but not from other packages (such as p3
)?
If I stretch your rules to their limits, it is possible. Though I'm not sure if that's intended or that you forgot a rule.
scala> :paste -raw
// Entering paste mode (ctrl-D to finish)
package p1 {
object O { private[p1] def f = println("f") }
package p2 {
object O { def x = p1.O.f }
}
}
// Exiting paste mode, now interpreting.
scala> :paste -raw
// Entering paste mode (ctrl-D to finish)
package p3 {
object O { def x = p1.O.f }
}
// Exiting paste mode, now interpreting.
<pastie>:2: error: method f in object O cannot be accessed in object p1.O
object O { def x = p1.O.f }
^
There were compilation errors!
If p2
also can't be contained by p1
, I don't think there's a way to guarantee that f
can't be accessed from somewhere else. You can do some tricks with sealed traits and implicits.
package p2 {
object O { def x = p1.O.f }
}
package object p2 {
sealed trait Friend
private[p2] implicit val p2Friend: Friend = new Friend {}
}
package p1 {
object O { def f(implicit friend: p2.Friend) = println("f") }
}
package p3 {
object O { def x = p1.O.f(null) }
}
But now as you can see you can still cheat in package p3
. And without cheating f
can't be accessed in p1
itself, because p1
also doesn't have the necessary implicit.
You can check in f
whether or not friend
is null
. Then p3
can't really use f
but it will only fail at runtime, not at compile time. Although if someone is passing around null
they can't really complain if things blow up at runtime.