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

我知道 protected[P1] 修饰符x与 java 的 protected 相同。但是,如何只允许从包 P1 中扩展 A AND 的类/对象访问 Ax?

编辑:@Randal 问:“你为什么关心包装约束?这对你有什么好处?”

我有一个带有复杂类的大型项目。我把班级分成几个特质。但是某些特征中的某些成员打算仅用于某些(但不是全部)其他子特征。因此,我将所有需要可访问性的特征组织在一个包中。需要这些特征逻辑的可实例化类被放在另一个包中。但是该类只需要访问某些特征的成员。然后我希望只有需要的成员对班级可见:

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 回答