Scala(四):物件

奮鬥的only發表於2018-12-17
物件:Object
1.單例物件
2.伴生物件
3.擴充套件類或特質的物件
4.apply方法
5.應用程式物件
6.列舉
1.單例物件
Scala中沒有你靜態方法或靜態欄位,可以用object這個語法結構來實現這個目的。物件定義某個類的單個例項,包含了你想要的特性

object ObjectOps {
     private var lastNumber = 0
  def newUniqueNumber() = {lastNumber+=1;lastNumber}
  /*
   *物件的構造器在該物件第一次被使用時呼叫,在本例中,ObjectOps的構造器在Object.newUniqueNumber()的首次呼叫時執行
   * 如果一個物件從未被使用,那麼他的構造器也從未被呼叫
   * 物件本質上會擁有類的所有特性,只有一個例外——不能提供構造器引數
   * 對於在Java中使用單例物件的地方,在Scala中都可以用物件來實現
   *      1.作為存放工具函式或常量的地方
   *      2.高效的共享單個不可以變例項
   *      3.需要單個例項來協調某個服務時
   */
}

2.伴生物件
在Java中你會用到既有例項方法又有靜態方法的類
在Scala中你可以通過類與類同名的伴生物件來實現
 1 class Accounts {
 2   //l類和它的伴生物件可以互相訪問私有屬性,但是必須在同一個原始檔中
 3   val id = Accounts.newUniqueNumber()
 4   private var balance = 0.0
 5   def deposit(amount : Double){balance += amount}
 6 }
 7 /*
 8  *說明:類的伴生物件可以被訪問,但並不在作用域中,如上,Accounts類必須通過Accounts.newUniqueNumber()而不是直接
 9  * newUniqueNumber()來呼叫伴生物件的方法
10  */
11 object Accounts{ //伴生物件
12   private var lastNumber = 0
13   private def newUniqueNumber() = {lastNumber+=1;lastNumber}
14 }

 

3.擴充套件類或特質的物件
一個object可以擴充套件類以及一個或多個特質,其結果是一個擴充套件了指定類以及特質的類的物件,同時擁有在物件定義中給出的所有特性
 1 //一個有用的使用場景是給出可被共享的預設物件eg:在程式中引入一個可撤銷動作的類
 2 abstract  class UndoableAction(val desctiption : String ) {
 3     def undo() : Unit
 4     def redo() : Unit
 5 }
 6 
 7 object DoNotingAction extends UndoableAction("Do Thing"){
 8   override def undo(): Unit = {}
 9 
10   override def redo(): Unit = {}
11   //DoNotingAction物件可以被所有需要這個預設行為的地方公用
12   val actions = Map("open" -> DoNotingAction,"save" -> DoNotingAction)
13 }

4.apply方法

Object(引數列表),此時apply方法會被呼叫
這樣返回的是半生類的物件
Array物件定義了apply方法,我們可以這樣來建立陣列
Array("John","had","Alice")
為什麼不用構造器呢?對於巢狀表示式而言,省去new會方便很多
Array(Array(1,2),Array("a","b"))
 1 class Account private (val id : Int ,initialBalance : Double){
 2     private var balance = initialBalance
 3 }
 4 
 5 object Account{
 6   private var lastNumber = 0
 7   private def newUniqueNumber() = {lastNumber+=1;lastNumber}
 8   def apply(initialBalance : Double): Unit ={
 9     new Account( newUniqueNumber(),initialBalance )
10   }
11   //這樣一來就可以如下這種方式來構造賬號了:
12 
13 
14   def main(args: Array[String]): Unit = {
15     val acct = Account(1000.0)
16 
17   }
18 }
5.應用程式物件
每個Scala程式都必須從一個物件的main方法開始。,這個方法的型別為Array[String]=>Unit:
 1 object Hello1 {
 2   def main(args: Array[String]): Unit = {
 3     println("Hello world")
 4   }
 5 }
 6 // 除了每次都提供main方法外,你也可以擴充套件APP特質,然後將程式程式碼放入構造器方法體內
 7 object Hello2 extends App{
 8   println("Hello world")
 9   //如果怒需要命令列引數,則可以通過args屬性得到:
10   if(args.length > 0){
11     println("hello" + args(0))
12   }else{
13     println("Hello world")
14   }
15 }

 

6.列舉
和Java不一樣,Scala中沒有列舉型別,不過標準類庫提供了一個Enumeration助手類,用於產出列舉
定義一個擴充套件Enumeration類的物件,並以Value方法呼叫初始化列舉中的所有可選值
object EnumOps extends Enumeration{
  //val Red,Yellow,Blue = Value
  /*
   *在這裡我們定義了三個欄位Red,Yellow,Blue,然後用value呼叫將他們初始化,這是如下程式碼的簡寫
   * val Red = Value
   * val Yellow = value
   * val Blue = value
   * 每次呼叫都會返回內部類的新例項,該內部類叫Value
   * 或者你也可以向Value傳入ID,名稱,或者兩個都傳
   */
  val Red = Value(0,"Stop")
  val Yellow = Value(10)
  val Blue = Value("GO")
  //如果不指定,則ID將前一個列舉值基礎上加1,從零開始,預設名稱為欄位名
  //定義完成後就可以通過EnumOps.Red來引用列舉值了
  //也可以通過 import EnumOps._

}

object LightColor extends Enumeration{
  type LightColor = Value
  val Red,Yellow,Blue = Value

  import LightColor._
  def doWhat(color : LightColor): Unit ={
      if(color == Red) "Stop"
      else if(color == Yellow) "hurry up"
      else "Go"
  }
  //列舉值的ID可以通過ID方法返回,名稱通過toString返回
  def main(args: Array[String]): Unit = {
    for(c <-LightColor.values) println(c.id +":"+ c)
    //最後,你可以通過列舉值或名稱來查詢定位
    LightColor(0)
    LightColor.withName("Red")
  }
}

 

 
 
 
 

相關文章