2013-02-25 18 views
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 
    } 
    } 
} 

我知道x上的保护[P1]修饰符与java的保护相同。但是,如何仅允许通过扩展包A中的A AND的类/对象来访问A.x?scala:类成员只能从子类访问,而子类必须在同一个包中。怎么样?

编辑: @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 
} 
+0

为什么你关心软件包约束?这会给你带来什么? – 2013-02-25 15:57:35

+0

特征定义类型。实现/扩展特质的具体类_cannot_撤消对特性中定义的成员的访问。这是我们所谓的“面向对象”软件的基本属性。 – 2013-02-26 04:54:59

+0

我不想/试图撤销辅助功能。我想要一种方法来定义特征 – 2013-02-27 04:35:40

回答

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

}

+0

的可访问性权利哦。你的解决方案非常好,但并不完美:D。你认为scala应该为这个用例提供一个不太详细的解决方案吗? – 2013-02-26 04:24:54

+0

访问限定符仅允许在正确的位置访问。它有2个方向:水平(包[p](和子包))和垂直(子类(或子特性))。有时我们希望将限定符与“OR”组合(如protected [p] = java的protected)。但有时候我们需要“AND”(我的用例)。 – 2013-02-26 04:35:44

+0

您的解决方案并不实际:1.我们必须在许多方法中添加(隐含ev:A#OnlyA)。为了将这种技术应用于领域,我们需要一个更加冗长的愚蠢代码。 – 2013-02-26 04:44:59

0

可以保护构造与private[PkgName]和供应厂家提供公众创造这样子类仅限于该包:

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

    object A { 
    def apply(): A = new A 
    } 
    ... 
+0

@BùiViệtThành:请修改你的问题。代码在评论中无法阅读。 (请在打开大括号之前放一个空格。) – 2013-02-26 02:45:31

+0

package a:class private [a] {val x = 1}。 B类扩展A.包B:C类扩展B {def f = x}。我想在B中拒绝访问x。怎么样? – 2013-02-26 02:59:41

+0

对不起...请在原始问题_中提出修正案。我不打算在评论中重新格式化代码以使其可读。然而,你根本无法扩展一个类(或特质)并减少访问 - 它违反了Liskov替换原则,一方面。 – 2013-02-26 03:12:03

相关问题