Christian Schlichtherle
Christian Schlichtherle

Reputation: 3155

I can haz no package-private class in Scala?

Sorry for the catchy title. ;-)

I want to create a package-private class with a package-private method in Scala, so my class looks somewhat like this:

package net.java.truevfs.ext.pace

import ...

private[pace] abstract class AspectController(controller: FsController)
extends FsDecoratingController(controller) {

  private[pace] def apply[V](operation: => V): V

  ... // lots of other stuff
}

However, if I use javap to check what the Scala compiler effectively creates, I get something like this:

$ javap -classpath target/classes net.java.truevfs.ext.pace.AspectController
Compiled from "AspectController.scala"
public abstract class net.java.truevfs.ext.pace.AspectController extends net.java.truevfs.kernel.spec.FsDecoratingController implements scala.ScalaObject{
    public abstract java.lang.Object apply(scala.Function0);
    ...
}

This means that although the Scala compiler might respect the access restrictions, I could still call this class from any Java code, which is a clear encapsulation violation.

Am I missing something? Is there a way to make this work as intended?

Upvotes: 18

Views: 5081

Answers (3)

JasonG
JasonG

Reputation: 5962

Not really a 100% correct answer...

You can make a package object if I want to do some fancy stuff in there with a private class. The package object is accessed like any other package. The class MyClass is package private to that package object. It's not package private however.

package object com.jasongoodwin.foo {
  private class MyClass

  class AnotherClass {
    val myClass = new MyClass
  }
}

Upvotes: 1

Alexey Romanov
Alexey Romanov

Reputation: 170713

In addition to @Régis' answer, the reason Scala compiler doesn't make the class package-private is because by Scala rules it can be accessed from other packages: namely, subpackages of net.java.truevfs.ext.pace. E.g.

package net.java.truevfs.ext.pace.subpackage
import net.java.truevfs.ext.pace.AspectController

class Subclass extends AspectController { ... }

is legal in Scala, but in Java classes from net.java.truevfs.ext.pace.subpackage can't access package-private classes from net.java.truevfs.ext.pace.

Upvotes: 15

Régis Jean-Gilles
Régis Jean-Gilles

Reputation: 32719

You are not missing anything. Many of the access restricitons in scala have no equivalent in java nor at the jvm level. The additional information is obviously right there in the .class file, but is there as custom annotations that only the scala compiler will interpret. The scala object model can only partly be matched to the jvm object model, and a java compiler will only see this partial model. I'd say that the match is pretty close and the scala compiler does a very good job at java interoperability, but nothings's perfect.

Upvotes: 10

Related Questions