scala的訪問修飾符有如下幾個特性: 如果不指定訪問修飾符,scala預設為public; 較之Java,scala對protected的定義更加嚴格; scala可以對可見性進行細粒度的控制。 scala的預設訪問修飾符 如果沒有修飾符,scala會預設把類、欄位、方法的訪問修飾符當做publi... ...
scala的訪問修飾符有如下幾個特性:
- 如果不指定訪問修飾符,scala預設為public;
- 較之Java,scala對protected的定義更加嚴格;
- scala可以對可見性進行細粒度的控制。
scala的預設訪問修飾符
如果沒有修飾符,scala會預設把類、欄位、方法的訪問修飾符當做public。如果要將之調整為private或protected,只需在前面添加對應的修飾符關鍵字即可。就如下麵的程式:
class Microwave{ def start() = println("started") def stop() = println("stopped") private def turnTable() = println("turning table") } val microwave = new Microwave microwave.start() microwave.turnTable()//這裡錯了
在上面的代碼里start和stop兩個方法被定義為public類型,可以通過任意Microwave實例訪問;turnTable被顯示定義為private,這樣就不能在Microwave類外部訪問它。執行這段代碼,就會如註釋處聲明的一樣,會在該處報錯:
protected修飾符
在scala里,用protected修飾的成員只對本類和派生類可見,同一個包內的其他的類不可見。而且派生類只可以訪問本類實例的protected成員。可以通過一個例子看一下:
package com.zhyea.scala.autos /** * Created by robin on 2016/6/12. */ class Vehicle { protected def checkEngine() = println("checked engine") } class Car extends Vehicle { def start() {checkEngine()} def tow(car : Car) { car.checkEngine() } def tow(vehicle: Vehicle){ vehicle.checkEngine()//會報錯 } } class GasStation{ def fillGas(vehicle : Vehicle){ vehicle.checkEngine()//會報錯 } }
編譯這段代碼會報錯:
在這段代碼里,Vehicle的checkEngine()方法是protected型的。scala允許我們通過Vehicle的派生類Car的實例方法(start())訪問這個方法,也允許我們在Car的實例方法里通過Car的實例來訪問這個方法,但是不允許在Car的實例方法里用Vehicle的實例訪問checkEngine()方法,同一包內的其他類也不行。(好繞,不過真是保護到了極致:只輸出方案不輸出資源,狗腿子軍師)
細粒度訪問控制
一方面scala對待protected比Java更加嚴格,另一方面它提供了更多的靈活性和更細粒度的訪問規則。
private和protected可以指定額外的參數。這樣,現在可以使用private[AccessQualifier],AccessQualifier可以是this,也可以是其它的類名或包名。這樣就可以這麼理解:這個成員對所有類都是private,除了自己和AccessQualifier所表示範圍內的類。這個概念也是可以遞推的,也就是說,如果AccessQualifier是一個類,那麼private成員對於AccessQualifier的AccessQualifier也是可見的。
看一個細粒度訪問控制的例子:
/** * Created by robin on 2016/6/13. */ package society { package professional { class Executive { private[professional] var workDetails = null private[society] var friends = null private[this] var secret = null def help(another: Executive) { println(another.workDetails) println(this.secret) println(another.secret) //會報錯 } } } package social { class Acquaintance { def socialize(person: professional.Executive) { println(person.friends) println(person.workDetails) //會報錯 } } } }
這段代碼裡面有一個嵌套包的使用:可以看到,在society包里又聲明瞭professional和social兩個包。而且使用包的方式也和之前不一樣,之前使用的是點號分隔,文件頭聲明的方式。
在類Executive的定義中,三個私有成員變數有著不同的作用範圍。workDetails對包professional內的類可見,friends對society包內的類可見,而secret只對當前實例可見。
所以編譯這段代碼,在標記報錯的地方會報錯:
secret只對當前實例this可見,對Executive的其他實例不可見。workDetails對包professional內的類可見,對society包內的類不可見。因此會報錯。
##########