18

キャッチーなタイトルでごめんなさい。;-)

Scalaでpackage-privateメソッドを使用して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コードから呼び出すことができることを意味します。これは、明らかにカプセル化違反です。

私は何かが足りないのですか?これを意図したとおりに機能させる方法はありますか?

4

3 に答える 3

15

@Régisの答えに加えて、Scalaコンパイラーがクラスをpackage-privateにしない理由は、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 に答える