0
object P{
  object P1{
    class A{
      //I want only classes/objects that extends A AND in the package P1 can access x
      //It means, the modifier `protected` and the qualifier [P1] is combined with operator `AND`:
      //protected AND [P1] means, x is:
      //    protected: not in subclass then not accessible
      //    AND [P1]: not in [P1] then not accessible
      //protected OR [P1] means, x is:
      //    protected: not in subclass then not accessible
      //    OR [P1]: not in [P1] then not accessible
      protected[P1] val x = 1

      //Like `protected[this]`: y is protected AND [this]
      //because y is accessible only in subclass AND in the same object
      //(access to y in B2.f2 is permit but in B2.f3 is deny)
      //(if protected[this] == protected OR [this] then protected[this] == protected :D)
      protected[this] val y = 2

      //Also, I don't know why the following code is valid
      //(scalac 2.10.0 compile it!). Is this an error in scala compiler?
      //But this strange modifiers combination is also not what I want!
      private[P1] protected val z = 1
    }
    class B{
      def f(a: A) = a.x + a.z //permit!
    }
  }
  object P2{
    class B2 extends P1.A{
      def f = x + z //also permit!
      def f2 = y //permit. OK
      def f3(b: B2) = b.y //deny. OK
    }
  }
}

xprotected[P1] 修飾子が Java の保護と同じであることは知っています。しかし、パッケージ P1 で A AND を拡張するクラス/オブジェクトからのみ Ax へのアクセスを許可するにはどうすればよいでしょうか?

編集: @Randal は次のように尋ねます。

複雑なクラスを持つ大規模なプロジェクトがあります。クラスをいくつかの特性に分割しました。しかし、いくつかの特性の一部のメンバーは、他のサブ特性の一部 (すべてではない) でのみ使用されることを意図しています。そのため、アクセシビリティが必要なすべての特性を 1 つのパッケージにまとめています。そして、それらの特性のロジックを必要とするインスタンス化可能なクラスは、別のパッケージに入れられます。ただし、クラスは一部の特性のメンバーにのみアクセスする必要があります。次に、必要なメンバーのみがクラスに表示されるようにします。

package p.base
private[base] trait A{
  //x is intent to be used only in trait B and C
  protected[base] val x = 1
}
private[base] trait B{this: A =>
  //f is intent to be used only in trait C
  protected[base] def f = x
  //f2 will be used in global.D
  def f2 = f
}
private[p] trait C extends B with A{...}

package p.global
class D extends p.base.C{
  def g = f2
}
4

2 に答える 2

0

特殊なアクセス修飾子のみを使用することはできません。コンパイル時間の制限を取得するには、次のような手法を使用できます

object P {
  object P1 {

    class A {
      @implicitNotFound(msg = "Only accessible when extending from A")
      sealed trait OnlyA
      protected[this] implicit object OnlyA extends OnlyA

      private[P1] def x(implicit ev: A#OnlyA) = 1

      private[P1] val z = 1
    }

    class B {
      def f(a: A) = a.z + a.x         // Will not work
    }
    class C extends A {
      def f(a: A) = a.z + a.x         // Works
    }
  }
  object P2 {

    class B2 extends P1.A {
      def f = x                       // Will not work
      def f(a: P1.A) = a.x + a.z      // Will not work
    }
  }

}

于 2013-02-25T16:01:34.153 に答える
0

サブクラス化がそのパッケージに限定されるように、パブリック作成を提供するためにコンストラクターを保護しprivate[PkgName]、ファクトリを提供できます。

package pkg
...
  class A private[pkg] { ...
  }

  object A {
    def apply(): A = new A
  }
  ...
于 2013-02-25T16:01:41.723 に答える