我可以在Scala中没有包私有类吗?

Chr*_*rle 17 scala

对不起,这个引人注目的标题.;-)

我想在Scala中使用package-private方法创建一个包私有类,所以我的类看起来像这样:

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
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我使用javap来检查Scala编译器有效创建的内容,我会得到这样的结果:

$ 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);
    ...
}
Run Code Online (Sandbox Code Playgroud)

这意味着尽管Scala编译器可能会尊重访问限制,但我仍然可以从任何Java代码中调用此类,这是一种明显的封装违规.

我错过了什么吗?有没有办法使这项工作按预期进行?

Ale*_*nov 15

除了@Régis的答案之外,Scala编译器没有使类包私有的原因是因为通过Scala规则它可以从其他包访问:即子包net.java.truevfs.ext.pace.例如

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

class Subclass extends AspectController { ... }
Run Code Online (Sandbox Code Playgroud)

在Scala中是合法的,但在Java类net.java.truevfs.ext.pace.subpackage中无法访问来自的包 - 私有类net.java.truevfs.ext.pace.


Rég*_*les 9

你没有遗漏任何东西.scala中的许多访问限制在java和jvm级别都没有等效.附加信息显然在.class文件中,但是作为自定义注释只有scala编译器会解释.scala对象模型只能部分匹配jvm对象模型,而java编译器只能看到这个部分模型.我会说匹配非常接近,scala编译器在java互操作性方面表现非常出色,但不是很完美.

  • 嗯,"无意义"与访问修饰符一般是毫无意义的相同程度,因为你总是可以通过反射/指针绕过它们. (3认同)