This does not work as expected (since I am trying to call a package private run
from outside Services
):
object Services {
class HelloPrinter {
private[Services] def run = "Hello"
}
}
val obj = new Services.HelloPrinter
But, surprisingly this works:
val obj: {def run: String} = new Services.HelloPrinter
obj.run
I would say, its a bug in the compiler since as HelloPrinter does not match the structural type because of package visibility rules, it should not compile at all!
Here is a case where the program compiles but it throws a runtime exception (java.lang.NoSuchMethodException
):
class HelloPrinter {
private[HelloPrinter] def run = "Hello"
}
val obj: {def run: String} = new HelloPrinter
obj.run
Is this a language feature or rule I am missing or legitimately a bug in Scala?
On the JVM level visibility scoped to surrounding instances/types does not exist. The Scala compiler will generate a public method in this case and handle this visibility internally.
If you use structural types the compiler will reflectively access the members of this type. It will not check Scala-specific visibility flags but only the ones defined in the Java bytecode.
You did not mention which version of the Scala compiler you are using but I assume that this is a bug in your specific version. I get the same result as Jasper-M when trying to compile it. The reason is that the method that is generated by the compiler is actually prefixed with the type name, i.e. HelloPrinter$$run
in this case. The following code will execute:
val x: { def HelloPrinter$$run: String } = new HelloPrinter
x.run
Again the Scala compiler just generates a public method and manages visibility internally. It is not a feature but rather a bug that the compiler does not check the Scala-internal visibility for structural types.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With