scala 訪問修飾符
scala 訪問修飾符基本和java的一樣,分別有:private,protected,public。
如果沒有指定訪問修飾符,默認情況下,scala 對象的訪問級別都是 public。
scala 中的 private 限定符,比 java 更嚴格,在嵌套類情況下,外層類甚至不能訪問被嵌套類的私有成員。
1. 私有(private)成員
用 private 關鍵字修飾,帶有此標記的成員僅在包含了成員定義的類或對象內部可見,同樣的規則還適用內部類。
class outer{ ? ? class inner{ ? ? ? ? private def f(){ ? ? ? ? ? ? println("f") ? ? ? ? } ? ? ? ? class innermost{ ? ? ? ? ? ? f() // 正確 ? ? ? ? } ? ? } ? ? (new inner).f() //錯誤 }
(new inner).f( ) 訪問不合法是因為 f 在 inner 中被聲明為 private,而訪問不在類 inner 之內。
但在 innermost 里訪問 f 就沒有問題的,因為這個訪問包含在 inner 類之內。
java 中允許這兩種訪問,因為它允許外部類訪問內部類的私有成員。
2. 保護(protected)成員
在 scala 中,對保護(protected)成員的訪問比 java 更嚴格一些。因為它只允許保護成員在定義了該成員的的類的子類中被訪問。而在java中,用protected關鍵字修飾的成員,除了定義了該成員的類的子類可以訪問,同一個包里的其他類也可以進行訪問。
package p{ class super{ ? ? protected def f() {println("f")} ? ? } ? ? ? ? class sub extends super{ ? ? ? ? ? ? f() ? ? ? ? } ? ? ? ? class other{ ? ? ? ? ? ? ? ? (new super).f() //錯誤 ? ? ? ? } }
上例中,sub 類對 f 的訪問沒有問題,因為 f 在 super 中被聲明為 protected,而 sub 是 super 的子類。相反,other 對 f 的訪問不被允許,因為 other 沒有繼承自 super。而后者在 java 里同樣被認可,因為 other 與 sub 在同一包里。
3. 公共(public)成員
scala 中,如果沒有指定任何的修飾符,則默認為 public。這樣的成員在任何地方都可以被訪問。
class outer { ? ?class inner { ? ? ? def f() { println("f") } ? ? ? class innermost { ? ? ? ? ?f() // 正確 ? ? ? } ? ?} ? ?(new inner).f() // 正確因為 f() 是 public }
4. 作用域保護
scala中,訪問修飾符可以通過使用限定詞強調。格式為:
private[x] 或 protected[x]
這里的x指代某個所屬的包、類或單例對象。如果寫成private[x],讀作"這個成員除了對[…]中的類或[…]中的包中的類及它們的伴生對像可見外,對其它所有類都是private。
這種技巧在橫跨了若干包的大型項目中非常有用,它允許你定義一些在你項目的若干子包中可見但對于項目外部的客戶卻始終不可見的東西。
package bobsrockets{ ? ? package navigation{ ? ? ? ? private[bobsrockets] class navigator{ ? ? ? ? ?protected[navigation] def usestarchart(){} ? ? ? ? ?class legofjourney{ ? ? ? ? ? ? ?private[navigator] val distance = 100 ? ? ? ? ? ? ?} ? ? ? ? ? ? private[this] var speed = 200 ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? package launch{ ? ? ? ? import navigation._ ? ? ? ? object vehicle{ ? ? ? ? private[launch] val guide = new navigator ? ? ? ? } ? ? } }
上述例子中,類 navigator 被標記為 private[bobsrockets] 就是說這個類對包含在 bobsrockets 包里的所有的類和對象可見。
比如說,從 vehicle 對象里對 navigator 的訪問是被允許的,因為對象 vehicle 包含在包 launch 中,而 launch 包在 bobsrockets 中,相反,所有在包 bobsrockets 之外的代碼都不能訪問類 navigator。