2013-02-25 73 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

相關問題