自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

學(xué)習(xí)Scala類的定義,字段和方法

開(kāi)發(fā) 后端
本文節(jié)選自Martin Odersky,Lex Spoon和Bill Venners所著,Regular翻譯的《Programming in Scala》的第四章。Scala是一種針對(duì) JVM 將函數(shù)和面向?qū)ο蠹夹g(shù)組合在一起的編程語(yǔ)言。

類是對(duì)象的藍(lán)圖。一旦你定義了類,你就可以用關(guān)鍵字new從類的藍(lán)圖里創(chuàng)建對(duì)象。比方說(shuō),如果給出了類的定義:

51CTO編輯推薦:Scala編程語(yǔ)言專題

  1. class ChecksumAccumulator {  
  2.  // class definition goes here  
  3. }  

你就能創(chuàng)建ChecksumAccumulator對(duì)象:

  1. new CheckSumAccumulator 

類定義里,可以放置字段和方法,這些被籠統(tǒng)地稱為成員:member。字段,不管是用val或是用var定義的,都是指向?qū)ο蟮淖兞?。方法,用def定義,包含了可執(zhí)行的代碼。字段保留了對(duì)象的狀態(tài)或者數(shù)據(jù),而方法使用這些數(shù)據(jù)對(duì)對(duì)象做運(yùn)算工作。當(dāng)你實(shí)例化類的時(shí)候,執(zhí)行期環(huán)境會(huì)設(shè)定一些內(nèi)存來(lái)保留對(duì)象狀態(tài)的鏡像——也就是說(shuō),變量的內(nèi)容。舉例來(lái)說(shuō),如果你定義了ChecksumAccumulator類并給它一個(gè)叫做sum的var字段:

  1. class ChecksumAccumulator {  
  2.  var sum = 0 
  3. }  

并實(shí)例化兩次:

  1. val acc = new ChecksumAccumulator  
  2. val csa = new ChecksumAccumulator  

對(duì)象在內(nèi)存里的鏡像看上去大概是這樣的:

對(duì)象在內(nèi)存里的鏡像看上去大概是這樣的 

由于在類ChecksumAccumulator里面定義的字段sum是var,而不是val,你之后可以重新賦值給它不同的Int值,如:

  1. acc.sum = 3 

現(xiàn)在,圖像看上去會(huì)變成:

 

這張圖里***件要注意的事情是這里有兩個(gè)sum變量,一個(gè)在acc指向的對(duì)象里,另一個(gè)在csa指向的對(duì)象里。字段的另一種說(shuō)法是實(shí)例變量:instance variable,因?yàn)槊恳粋€(gè)實(shí)例都有自己的變量集??傮w來(lái)說(shuō),對(duì)象實(shí)例的變量組成了對(duì)象的內(nèi)存鏡像。你不僅可以因?yàn)榭吹絻蓚€(gè)sum變量來(lái)體會(huì)關(guān)于這個(gè)的演示,同樣可以通過(guò)改變其中一個(gè)時(shí),另一個(gè)不變來(lái)發(fā)現(xiàn)這點(diǎn)。

本例中另外一件需要注意的事情是,盡管acc是val,你仍可以改變acc指向的對(duì)象。你對(duì)acc(或csa)不能做的事情是由于它們是val,而不是var,你不可以把它們?cè)俅钨x值為不同的對(duì)象。例如,下面的嘗試將會(huì)失?。?/P>

  1. // 編譯不過(guò),因?yàn)閍cc是val  
  2. acc = new ChecksumAccumulator  

于是你可以總結(jié)出來(lái),acc將永遠(yuǎn)指向初始化時(shí)指向的同一個(gè)ChecksumAccumulator對(duì)象,但是包含于對(duì)象中的字段可以隨時(shí)改動(dòng)。
想讓對(duì)象具有魯棒性的一個(gè)重要的方法就是保證對(duì)象的狀態(tài)——實(shí)例變量的值——在對(duì)象整個(gè)生命周期中持續(xù)有效。***步就是通過(guò)把字段變?yōu)?EM>私有的:private去阻止外界直接對(duì)它的訪問(wèn),因?yàn)樗接凶侄沃荒鼙欢x在同一個(gè)類里的方法訪問(wèn),所有能更新字段的代碼將被鎖定在類里。要聲明字段是私有的,可以把訪問(wèn)修飾符private放在字段的前面,就像這樣:

  1. class ChecksumAccumulator {  
  2.  private var sum = 0 
  3. }  

有了這個(gè)ChecksumAccumulator的定義,任何從類外部訪問(wèn)sum的嘗試都會(huì)失?。?BR>

  1. val acc = new ChecksumAccumulator  
  2. acc.sum = 5 //編譯不過(guò),因?yàn)閟um是私有的  

注意

在Scala里把成員公開(kāi)的方法是不顯式地指定任何訪問(wèn)修飾符。換句話說(shuō),你在Java里要寫上“public”的地方,在Scala里只要什么都不要寫就成。Public是Scala的缺省訪問(wèn)級(jí)別。

現(xiàn)在sum是私有的,所以唯一能訪問(wèn)sum的代碼是定義在類自己里面的。這樣,除非我們定義什么方法,否則ChecksumAccumulator對(duì)任何人都沒(méi)什么用處:

  1. class ChecksumAccumulator {  
  2.  private var sum = 0 
  3.  def add(b: Byte): Unit =  {  
  4.   sum += b  
  5.  }  
  6.  def checksum(): Int = {  
  7.   return ~(sum & 0xFF) + 1 
  8.  }  
  9. }  

現(xiàn)在ChecksumAccumulator有兩個(gè)方法了,add和checksum,兩個(gè)都以基本的的函數(shù)定義方式展示,參見(jiàn)第38頁(yè)的圖2.1。
傳遞給方法的任何參數(shù)都可以在方法內(nèi)部使用。Scala里方法參數(shù)的一個(gè)重要特征是它們都是val,不是var。參數(shù)是val的理由是val更容易講清楚。你不需要多看代碼以確定是否val被重新賦值,而var則不然。 如果你想在方法里面給參數(shù)重新賦值,結(jié)果是編譯失?。?BR>

  1. def add(b: Byte): Unit = {  
  2.  b += 1 // 編譯不過(guò),因?yàn)閎是val  
  3.  sum += b  
  4. }  

盡管在這個(gè)ChecksumAccumulator版本里的add和checksum方法正確地實(shí)現(xiàn)了預(yù)期的功能,你還是可以用更簡(jiǎn)潔的風(fēng)格表達(dá)它們。首先,checksum方法***的return語(yǔ)句是多余的可以去掉。如果沒(méi)有發(fā)現(xiàn)任何顯式的返回語(yǔ)句,Scala方法將返回方法中***一個(gè)計(jì)算得到的值。

對(duì)于方法來(lái)說(shuō)推薦的風(fēng)格實(shí)際是避免顯式的尤其是多個(gè)返回語(yǔ)句。代之以把每個(gè)方法當(dāng)作是創(chuàng)建返回值的表達(dá)式。這種哲學(xué)將鼓勵(lì)你制造很小的方法,把較大的方法分解為多個(gè)更小的方法。另一方面,設(shè)計(jì)選擇取決于設(shè)計(jì)內(nèi)容,Scala使得編寫具有多個(gè),顯式的return的方法變得容易,如果那的確是你期望的。

因?yàn)閏hecksum要做的只有計(jì)算值,不需要return。所以這個(gè)方法的另一種簡(jiǎn)寫方式是,假如某個(gè)方法僅計(jì)算單個(gè)結(jié)果表達(dá)式,則可以去掉大括號(hào)。如果結(jié)果表達(dá)式很短,甚至可以把它放在def同一行里。這樣改動(dòng)之后,類ChecksumAccumulator看上去像這樣:

  1. class ChecksumAccumulator {  
  2.  private var sum = 0 
  3.  def add(b: Byte): Unit = sum += b  
  4.  def checksum(): Int = ~(sum & 0xFF) + 1 
  5. }  

像ChecksumAccumulator的add方法那樣的結(jié)果類型為Unit的方法,執(zhí)行的目的就是它的副作用。通常我們定義副作用為在方法外部某處改變狀態(tài)或者執(zhí)行I/O活動(dòng)。比方說(shuō),在add這個(gè)例子里,副作用就是sum被重新賦值了。表達(dá)這個(gè)方法的另一種方式是去掉結(jié)果類型和等號(hào),把方法體放在大括號(hào)里。這種形式下,方法看上去很像過(guò)程:procedure,一種僅為了副作用而執(zhí)行的方法。代碼4.1的add方法里演示了這種風(fēng)格:

  1. // 文件ChecksumAccumulator.scala  
  2. class ChecksumAccumulator {  
  3.  private var sum = 0 
  4.  def add(b: Byte) { sum += b }  
  5.  def checksum(): Int = ~(sum & 0xFF) + 1 
  6. }  

代碼 4.1 類ChecksumAccumulator的最終版
應(yīng)該注意到令人困惑的地方是當(dāng)你去掉方法體前面的等號(hào)時(shí),它的結(jié)果類型將注定是Unit。不論方法體里面包含什么都不例外,因?yàn)镾cala編譯器可以把任何類型轉(zhuǎn)換為Unit。例如,如果方法的***結(jié)果是String,但方法的結(jié)果類型被聲明為Unit,那么String將被轉(zhuǎn)變?yōu)閁nit并失去它的值。下面是這個(gè)例子:

  1. scala> def f(): Unit = "this String gets lost" 
  2. f: ()Unit  

例子里,String被轉(zhuǎn)變?yōu)閁nit因?yàn)閁nit是函數(shù)f聲明的結(jié)果類型。Scala編譯器會(huì)把一個(gè)以過(guò)程風(fēng)格定義的方法,就是說(shuō),帶有大括號(hào)但沒(méi)有等號(hào)的,在本質(zhì)上當(dāng)作是顯式定義結(jié)果類型為Unit的方法。例如:

  1. scala> def g() { "this String gets lost too" }  
  2. g: ()Unit  

因此,如果你本想返回一個(gè)非Unit的值,卻忘記了等號(hào)時(shí),那么困惑就出現(xiàn)了。所以為了得到你想要的結(jié)果,你需要插入等號(hào):

  1. scala> def h() = { "this String gets returned!" }  
  2. h: ()java.lang.String  
  3. scala> h  
  4. res0: java.lang.String = this String gets returned!  

【相關(guān)閱讀】

  1. 學(xué)習(xí)Scala腳本:從文件里讀取行記錄
  2. 學(xué)習(xí)識(shí)別Scala的函數(shù)式風(fēng)格
  3. Scala編程實(shí)例:使用Set和Map
  4. Scala編程實(shí)例:使用List和Tuple
  5. Scala編程實(shí)例:帶類型的參數(shù)化數(shù)組

【責(zé)任編輯:王苑 TEL:(010)68476606】

責(zé)任編輯:book05 來(lái)源: Artima
相關(guān)推薦

2009-07-22 08:34:47

Scala方法和字段

2009-07-21 12:47:04

Scala私有字段定義操作符

2009-12-11 10:42:00

Scala講座類定義構(gòu)造函數(shù)

2009-07-08 15:35:18

Case類Scala

2009-07-21 13:54:55

Scala重載方法隱式轉(zhuǎn)換

2009-09-09 11:28:40

Scala類

2009-07-22 09:22:20

Scala工廠對(duì)象

2009-07-21 17:21:57

Scala定義函數(shù)

2009-09-09 11:37:08

Scala的模式匹配

2009-06-16 17:54:38

Scala類語(yǔ)法語(yǔ)義

2009-07-22 07:50:00

Scala二維布局庫(kù)抽象類

2009-07-22 07:53:00

Scala無(wú)參數(shù)方法

2009-07-21 11:25:03

ScalaRational類

2009-07-22 08:45:35

Scala超類構(gòu)造器override修飾符

2010-11-23 15:27:00

MySQL添加字段

2009-11-16 17:04:46

Inside Scal

2009-07-21 16:58:31

Scala變量范圍

2009-07-22 07:43:00

Scala閉包

2009-07-22 07:53:00

Scala擴(kuò)展類

2011-07-06 14:12:14

Objective-C
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)