18

对不起,吸引人的标题。;-)

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

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 代码调用这个类,这显然违反了封装。

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

4

3 回答 3

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 { ... }

在 Scala 中是合法的,但在 Java 类net.java.truevfs.ext.pace.subpackage中不能从net.java.truevfs.ext.pace.

于 2012-10-09T15:25:09.633 回答
10

你没有错过任何东西。scala 中的许多访问限制在 java 和 jvm 级别都没有等效项。附加信息显然就在 .class 文件中,但作为只有 scala 编译器会解释的自定义注释存在。scala 对象模型只能部分匹配到 jvm 对象模型,java 编译器只会看到这个部分模型。我想说匹配非常接近,scala 编译器在 java 互操作性方面做得很好,但没有什么是完美的。

于 2012-10-09T10:31:40.713 回答
1

不是一个100%正确的答案......

如果我想用私有类做一些花哨的东西,你可以制作一个包对象。可以像访问任何其他包一样访问包对象。MyClass 类是该包对象的包私有。但是,它不是私有包。

package object com.jasongoodwin.foo {
  private class MyClass

  class AnotherClass {
    val myClass = new MyClass
  }
}
于 2014-04-10T19:59:26.323 回答