很抱歉这个引人注目的标题。 ; - )
我想在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
}
但是,如果我使用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);
...
}
这意味着尽管Scala编译器可能会尊重访问限制,但我仍然可以从任何Java代码中调用此类,这是一种明显的封装违规。
我错过了什么吗? 有没有办法让这项工作按预期进行?
答案 0 :(得分:15)
除了@Régis的回答之外,Scala编译器没有使类包私有的原因是因为通过Scala规则可以从其他包中访问 :即{{{}的子包1}}。 E.g。
net.java.truevfs.ext.pace
在Scala中是合法的,但是package net.java.truevfs.ext.pace.subpackage
import net.java.truevfs.ext.pace.AspectController
class Subclass extends AspectController { ... }
中的Java类无法从net.java.truevfs.ext.pace.subpackage
访问包私有类。
答案 1 :(得分:9)
你没有遗漏任何东西。 scala中的许多访问限制在java和jvm级别都没有等效。附加信息显然在.class文件中,但是作为自定义注释只有scala编译器会解释。 scala对象模型只能部分匹配jvm对象模型,而java编译器只能看到这个部分模型。 我会说匹配非常接近,scala编译器在java互操作性方面表现非常出色,但不是很完美。
答案 2 :(得分:1)
不是100%正确答案......
如果我想在私人课程中做一些奇特的东西,你可以制作一个包对象。可以像访问任何其他包一样访问包对象。 MyClass类是该包对象的私有包。 但是,它不是私有包。
package object com.jasongoodwin.foo {
private class MyClass
class AnotherClass {
val myClass = new MyClass
}
}