Scala:重載方法和字段及定義參數(shù)化字段
重載方法和字段
統(tǒng)一訪問原則只是Scala在對待字段和方法方面比Java更統(tǒng)一的一個方面。另一個差異是Scala里,字段和方法屬于相同的命名空間。這使得字段重載無參數(shù)方法成為可能。比如說,你可以改變類ArrayElement中contents的實(shí)現(xiàn),從一個方法變?yōu)橐粋€字段,而無需修改類Element中contents的抽象方法定義,如展示在代碼10.4中的那樣:
- class ArrayElement(conts: Array[String]) extends Element {
- val contents: Array[String] = conts
- }
代碼 10.4 用字段重載無參數(shù)方法
51CTO編輯推薦:Scala編程語言專題
這個ArrayElement的版本里,字段contents(用val定義)完美地實(shí)現(xiàn)了類Element里的無參數(shù)方法contents(用def定義)。
另一方面,Scala里禁止在同一個類里用同樣的名稱定義字段和方法,而在Java里這樣做被允許。例如,下面的Java類能夠很好地編譯:
但是相應(yīng)的Scala類將不能編譯:
- // 在Java里的代碼
- class CompilesFine {
- private int f = 0;
- public int f() {
- return 1;
- }
- }
- class WontCompile {
- private var f = 0 // 編譯不過,因?yàn)樽侄魏头椒ㄖ孛?
- def f = 1
- }
通常情況下,Scala僅為定義準(zhǔn)備了兩個命名空間,而Java有四個。Java的四個命名空間是字段,方法,類型和包。與之相對,Scala的兩個命名空間是:
值(字段,方法,包還有單例對象)
類型(類和特質(zhì)名)
Scala把字段和方法放進(jìn)同一個命名空間的理由很清楚,因?yàn)檫@樣你就可以使用val重載無參數(shù)的方法,這種你在Java里做不到的事情。Scala里包共享了與字段和方法相同的命名空間的原因是為了讓你能除了僅僅引用類型名以及單例對象的字段和方法之外,還能直接引用包。這同樣是你在Java中無法做到的。
定義參數(shù)化字段
再次考慮上一節(jié)中展示的ArrayElement類的定義。它有一個參數(shù)conts,其唯一目的是被復(fù)制到contents字段。選擇conts這個參數(shù)的名稱只是為了讓它看上去更像字段名contents而不會與它發(fā)生實(shí)際沖突。這是一種“代碼味道”,一個表明或許某些不必須的榮譽(yù)和重復(fù)在你代碼中出現(xiàn)的信號。
你可以通過在單一的參數(shù)化字段:parametric field定義中組合參數(shù)和字段避免這種代碼味道,展示在代碼10.5中:
- class ArrayElement( // 請注意,小括號
- val contents: Array[String]
- ) extends Element
代碼 10.5 定義contents為參數(shù)化字段
注意現(xiàn)在contents參數(shù)前綴了val。這是在同一時間使用相同的名稱定義參數(shù)和字段的一個簡寫方式。尤其特別的是,類ArrayElement現(xiàn)在擁有一個可以從類外部訪問的,(不能重新賦值的)字段contents。字段使用參數(shù)值初始化。就好象類被寫成如下的方式,其中x123是參數(shù)的任意未曾用過的名字:
- class ArrayElement(x123: Array[String]) extends Element {
- val contents: Array[String] = x123
- }
同樣也可以使用var前綴類參數(shù),這種情況下相應(yīng)的字段將能重新被賦值。最終,還有可能添加如private,protected,protected修飾符,可以授權(quán)給子類訪問,將在第13章詳細(xì)描述。或override這類的修飾符到這些參數(shù)化字段上,就好象你可以在其他類成員上做的事情。比方說,考察下列類定義:
- class Cat {
- val dangerous = false
- }
- class Tiger(
- override val dangerous: Boolean,
- private var age: Int
- ) extends Cat
Tiger的定義是以下包括重載成員dangerous和private成員age的類定義替代寫法的簡寫:
- class Tiger(param1: Boolean, param2: Int) extends Cat {
- override val dangerous = param1
- private var age = param2
- }
兩個成員都初始化自相應(yīng)的參數(shù)。我們?nèi)我膺x擇了這些參數(shù)名,param1和param2。重要的是它們不會與范圍內(nèi)的任何其它名稱沖突。
【相關(guān)閱讀】
- Scala程序中的擴(kuò)展類
- 在Scala中定義無參數(shù)方法
- 學(xué)習(xí)Scala的二維布局庫和抽象類
- Scala學(xué)習(xí):叫名參數(shù)by-name parameter
- Scala:如何編寫新的控制結(jié)構(gòu)