1. 程式人生 > >Scala中的類和Object

Scala中的類和Object

Scala和java差不多定義類,使用class關鍵字

如下:

class CreateClassTest{

  //定義相應的類的欄位(fileds)
  var sum = 0
  //定義一個私有的變數,在Scala中公開成員的方法是不顯式指定任何訪問修飾符。
  //換句話說,在Java中你可以說public,而在Scala中你什麼都不說。Public是Scala的預設訪問級別
  private var privateVar = "this is a private var"

  //定義相關的方法
  def add(str : String): String ={
    privateVar += str
    return privateVar
  }

  def check(str: String): Boolean ={
    if(privateVar.startsWith(str)) true else false
  }

//這個和上面的check是一樣的效果

  def checkR(str: String): Boolean = if(privateVar.startsWith(str)) true else false

}

可以在類中建立類的欄位和方法,定義方法使用def 方法名

var acc = new CreateClassTest
var csa = new CreateClassTest

上面兩行是對類的引用,如果這裡acc宣告為val,不能重新分配一個新的物件
//acc.privateVar = "vister private var error"
//println(acc.privateVar)
//這裡將報錯,因為privateVar是私有的方法,只能在CreateClassTest類中進行訪問

Scala中的分號規則:

  對於語句分離的準確規則,它們的工作效果非常簡單。簡而言之,除非滿足下列條件之一,否則將行結尾視為分號:
 1.有問題的行以單詞形式結束,該單詞作為語句的結尾不合法,例如句點或中綴運算子 。
 2.下一行以一個無法啟動語句的單詞開頭。
 3.該行在括號(...)或括號[...]內結束,因為它們無論如何都不能包含多個語句

Scala中的靜態成員

Scala比Java更面向物件的一種方式是Scala中的類不能有靜態成員。相反,Scala有單例物件。單例物件定義看起來像類定義,只不過您使用關鍵字object而不是關鍵字class

import scala.collection.mutable.Map

class CreateObjectTest{
  private var sum = 0
  def checksum(): Int = ~(sum & 0xFF) + 1
  def add(b: Byte){sum += b}
}

//建立一個靜態成員

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

當單例物件與類共享相同的名稱時,它被稱為類CreateObjectTest的companion物件。您必須在同一個原始檔中定義類及其附屬物件。該類被稱為singleton物件的companion類。類和它的companion物件可以相互訪問其私有成員
println(CreateObjectTest.calculate("hello world tony single object"))
然而,單例物件不僅僅是靜態方法的持有者。它是一級物件。因此,可以將單例物件的名稱看作是附加到該物件的名稱標記
定義單例物件並不定義型別(在Scala抽象級別)。給定物件checksum累加器的定義,就不能建立checksum累加器型別的變數。相反,名為CreateObjectTest的型別是由singleton物件的companion類定義的。然而,單例物件擴充套件了一個超類,並且可以混合特徵,類和單例物件之間的一個區別是單例物件不能接受引數,而類可以。因為不能用new關鍵字例項化單例物件,
所以無法向其傳遞引數。每個單例物件都是作為一個從靜態變數引用的合成類的例項實現的,
因此它們具有與Java靜態相同的初始化語義。特別是,單例物件是在一些程式碼第一次訪問它時初始化的。
一個單例物件不與一個類共享相同的名稱,稱為獨立物件

Scala的程式入口和java的一樣,使用main方法,如下定義:

執行一個scala的應用,必須建立一個單例的物件與一個main方法,接受一個Array[String]的引數,
並且返回值為Unit的一個方法。和java基本類似,java為public static void main(String [] aegs){}

import CreateObjectTest.calculate   //引入其他的類

object Summer{
  def main(args: Array[String]){
    for(arg <- args)
      println(arg + " : " + calculate(arg))
  }
}

這裡我們需要編譯這兩個類:CreateObjectTest.scala和Summer.scala

可以使用

1.scalac CreateObjectTest.scala Summer.scala

2.fsc CreateObjectTest.scala Summer.scala 如果出現下面的介面

之後就可以運行了:

scala Summer tony lovess

這將編譯原始檔,但是在編譯完成之前可能會有明顯的延遲。原因是每次編譯器啟動時,它都要花時間掃描jar檔案的內容,並在檢視提交給它的新原始檔之前執行其他初始工作。出於這個原因,Scala發行版還包含一個名為fsc(用於快速Scala編譯器)的Scala編譯器守護程序.

第一次執行fsc時,它將建立一個本地伺服器守護程序,該守護程序連線到計算機上的一個埠。然後,它將通過埠將要編譯的檔案列表傳送給守護程序,守護程序將編譯這些檔案。下次執行fsc時,守護程序已經在運行了,因此fsc將簡單地將檔案列表傳送給守護程序,該守護程序將立即編譯檔案。使用fsc,您只需要等待Java執行時第一次啟動。如果您想停止fsc守護程序,可以通過fsc -shutdown來完成。執行這些scalac或fsc命令將生成Java類

如果我們不想寫main這個方法,可以繼承scala.Application這個類,但是這個類在scala版本2.9只有就已經過期了,改為App,如果在新版中使用Application的話,會包如下錯誤:

之後我們只需要將Applciation改為App,將能編譯成功:

import CreateObjectTest.calculate

object FallWinterSpringSummer extends App {
  for(season <- List("fall","Winter","Spring"))
    println(season + " : " + calculate(season))
}

但是如果使用了App的話,將不能取得命令列中的引數,因為命令列引數在這種情況下不可用。其次,由於JVM執行緒模型中的一些限制,如果您的程式是多執行緒的,則需要顯式main方法。最後,JVM的一些實現不優化由應用程式特徵執行的物件的初始化程式碼。因此,只有當您的程式相對簡單且單執行緒時,才應該從應用程式繼承