ETA: please see clarification here. Original question follows:
I just realized that a type alias can publicize a private type:
object A {
private[A] object B { def string = "" }
type Export = () => B.type
val export: Export = () => B
}
object C {
val b = A.export()
val string = b.string
}
This creates a weird situation: there is no type (other than Any) that I can explicitly write for C.b. The compiler knows what the type is, but I can’t mention it; writing val b: A.B = ... would fail. And I can go on to access methods like B.string that are supposed to be private[A] once I got a reference to B.
Interesting case. I’d say this behavior is desirable, because what else should the compiler do? You made the type Export public, and you can’t know what Export is unless you also know what B is.
This works: object A { private[A] trait B; def b: B = new B{} }
But this doesn’t: object A { private trait B; def b: B = new B{} }; compilation fails saying private trait B escapes its defining scope as part of type A.B.
The Scala spec on visibility modifiers doesn’t explain why this difference should be relevant. Can someone explain to me why there’s a difference in behavior?
Ok, after further consideration, I changed my mind and now I consider the behavior undesirable. Aliases should be required to have the same access restrictions.
The difference between private and private[A] should be access from the companion, but it should not be relevant here.