鍍金池/ 教程/ Scala/ 類和對象 (二)
包對象
Ordered Trait
組合和繼承–定義 final 成員
基本數(shù)據(jù)類型
Match 表達(dá)式
類和對象 (三)
操作基本數(shù)據(jù)類型
for 表達(dá)式
組合和繼承–重載成員函數(shù)和方法
類和對象 (二)
組合和繼承–定義 factory 對象
組合和繼承–多態(tài)和動態(tài)綁定
Trait 的基本概念
if 表達(dá)式
組合和繼承–抽象類
函數(shù)–函數(shù)字面量的一些簡化寫法
while 循環(huán)
組合和繼承–使用組合還是繼承?
訪問控制修飾符
Trait 示例–Rectangular 對象
組合和繼承–定義參數(shù)化成員變量
組合和繼承–定義無參數(shù)方法
類和對象 (一)
函數(shù)–閉包
函數(shù)–類成員函數(shù)
Scala 基本數(shù)據(jù)類型的實現(xiàn)方法
try 表達(dá)式處理異常
選擇瘦接口還是胖接口設(shè)計?
組合和繼承–小結(jié)
創(chuàng)建新的控制結(jié)構(gòu)
使用 import
為訪問控制修飾符添加作用域
Scala 的類層次關(guān)系
類和對象 (五)
傳名參數(shù)
柯里化函數(shù)
函數(shù)–頭等公民
組合和組合和繼承–定義 heighten 和 widen 函數(shù)
使用 Package–將代碼放入包中
隱含的 import
所有類的公共子類–底層類型
進(jìn)一步 Scala
函數(shù)–局部函數(shù)
引用包中的代碼
組合和繼承–使用 override 修飾符
組合和繼承–實現(xiàn)類 Element 的 above,beside 和 toString()方法
類和對象 (四)
函數(shù)–尾遞歸
沒有“break”和“continue”的日子
組合和繼承–調(diào)用基類構(gòu)造函數(shù)
減低代碼重復(fù)
函數(shù)–函數(shù)–可變參數(shù),命名參數(shù),缺省參數(shù)
起步 Scala
組合和繼承–擴(kuò)展類
函數(shù)–部分應(yīng)用的函數(shù)
開始神奇的 Scala編程之旅
組合和繼承–概述
Trait 用來實現(xiàn)可疊加的修改操作

類和對象 (二)

前面提到 Scala 比 Java 更加面向?qū)ο?,這是因為 Scala 不允許類保護(hù)靜態(tài)元素(靜態(tài)變量或靜態(tài)方法)。在 Scala 中提供類似功能的是成為“Singleton(單例對象)”的對象。在 Scala 中定義 Singleton 對象的方法除了使用 object,而非 class 關(guān)鍵字外和類定義非常類似,下面例子創(chuàng)建一個 ChecksumAccumulator 對象:

object ChecksumAccumulator {
   private val cache = Map [String, Int] ()
   def calculate(s:String) : Int =
      if(cache.contains(s))
         cache(s)
      else {
         val acc=new ChecksumAccumulator
         for( c <- s)
            acc.add(c.toByte)
         val cs=acc.checksum()
         cache += ( s -> cs)
         cs
       }
}

這個對象和上一篇創(chuàng)建的類 ChecksumAccumulator 同名,這在 Scala 中把這個對象成為其同名的類的“伴侶”對象( Companion object )。 如果你需要定義的類的 companion 對象,Scala 要求你把這兩個定義放在同一個文件中。類和其 companion 對象可以互相訪問對方的私有成員。

如果你是 Java 成員,可以把 Singleton 對象看成以前 Java 定義靜態(tài)成員的地方。你可以使用類似 Java 靜態(tài)方法的方式調(diào)用 Singleton 對象的方法,比如下面為這個例子完整的代碼:

import scala.collection.mutable.Map
class ChecksumAccumulator{
   private var sum=0
   def add(b:Byte) :Unit = sum +=b
   def checksum() : Int = ~ (sum & 0xFF) +1
}

object ChecksumAccumulator {
   private val cache = Map [String, Int] ()
   def calculate(s:String) : Int =
      if(cache.contains(s))
         cache(s)
      else {
         val acc=new ChecksumAccumulator
         for( c <- s)
            acc.add(c.toByte)
         val cs=acc.checksum()
         cache += ( s -> cs)
         cs
       }
}

println ( ChecksumAccumulator.calculate("Welcome to Scala Chinese community"))

Scala 的 singleton 對象不僅限于作為靜態(tài)對象的容器,它在 Scala 中也是頭等公民,但僅僅定義 Singleton 對象本身不會創(chuàng)建一個新的類型,你不可以使用 new 再創(chuàng)建一個新的 Singleton 對象(這也是 Singleton 名字的由來),此外和類定義不同的是,singleton 對象不可以帶參數(shù)(類定義參數(shù)將在后面文章介紹)。

回過頭來看看我們的第一個例子 “Hello World“。

object HelloWorld {
  def main(args: Array[String]) {
    println("Hello, world!")
  }
}

這是一個最簡單的 Scala 程序,HelloWorld 是一個 Singleton 對象,它包含一個 main 方法(可以支持命令行參數(shù)),和 Java 類似,Scala 中任何 Singleto 對象,如果包含 main 方法,都可以作為應(yīng)用的入口點。

在這里要說明一點的是,在 Scala 中不要求 public 類定義和其文件名同名,不過使用和 public 類和文件同名還是有它的優(yōu)點的,你可以根據(jù)個人喜好決定是否遵循 Java 文件命名風(fēng)格。

最后提一下 Scala 的 trait 功能,Scala 的 trait 和 Java 的 Interface 相比,可以有方法的實現(xiàn)(這點有點像抽象類,但如果是抽象類,就不會允許繼承多個抽象類)。Scala 的 Trait 支持類和 Singleton 對象和多個 Trait 混合(使用來自這些 Trait 中的方法,而不時不違反單一繼承的原則)。

Scala 為 Singleton 對象的 main 定義了一個 App trait 類型,因此上面的例子可以簡化為:

object HelloWorld extends App{
   println("Hello, world!")
}

這段代碼就不能作為腳本運行,Scala 的腳本要求代碼最后以表達(dá)式結(jié)束。因此運行這段代碼,需要先編譯這段代碼:

scalac Helloworld.scala

編譯好之后,運行該應(yīng)用

scala HelloWord

注意: Scala 提供了一個快速編譯代碼的輔助命令 fsc (fast scala compliler) ,使用這個命令,只在第一次使用 fsc時啟動 JVM,之后 fsc 在后臺運行,這樣就避免每次使用 scalac 時都要載入相關(guān)庫文件,從而提高編譯速度。