Scala(四)之“類和屬性”

主構造函數
Scala中爲類創建一個主構造函數和Java中不相同。
一個Scala類的主構造函數是以下的組合:

  • 構造函數參數
  • 在類內部被調用的方法
  • 在類內部執行的語句和表達式

下面的類說明了在類中的構造函數參數、類字段和語句:

class Person(var firstName: String, var lastName: String) {
  println("the contructor begins")

  // some class field
  private val HOME = System.getProperty("use.home")
  var age = 0

  // some method
  override def toString = s"$firstName $lastName is $age years old"
  def printHome{ print(s"HOME = $HOME")}
  def printFullName = {println(this)} // uses toString

  printHome
  printFullName
  println("still in the constructor")
}

注意:Scala中被private修飾的字段,不可以被其他對象直接訪問,並且其值也不可以改變。


控制構造函數字段的可見性
var字段:如果一個構造函數參數被聲明爲var,該字段的值是可變的,Scala會爲它生成getter和setter方法。

scala> class Person(var name: String)
defined class Person

scala> val p = new Person("Alvin Alexander")
p: Person = Person@4d1bf319
// getter
scala> p.name
res4: String = Alvin Alexander
// setter
scala> p.name = "gnahznib"
p.name: String = gnahznib

scala> p.name
res5: String = gnahznib

val字段:如果構造函數參數字段被定義爲val,那麼這個字段一旦被賦值就無法改變,就像Java中的final。因此,有訪問方法是很有必要的,但不應該有修改方法。

scala> class Person(val name: String)
defined class Person

scala> val p = new Person("Alvin Alexander")
p: Person = Person@5680a178

scala> p.name
res0: String = Alvin Alexander

scala> p.name = "gnahznib"
<console>:13: error: reassignment to val
       p.name = "gnahznib"
              ^

非val和非var的字段:當構造函數參數既沒有聲明爲val或var是,字段的可見性很受限制,並且Scala不會爲此生成訪問修改方法。

scala> class Person(name: String)
defined class Person

scala> val p = new Person("Alvin Alexander")
p: Person = Person@16b3fc9e

scala> p.name
<console>:14: error: value name is not a member of Person
       p.name
         ^

給val或var加上private:private關鍵字會阻止getter和setter方法的生成,所以這個字段只能被類的成員變量使用

scala> class People(private var name: String){def getName{println(name)}}
defined class People

scala> val p = new People("Alvin Alexander")
p: People = People@4493d195

scala> p.name
<console>:14: error: variable name in class People cannot be accessed in People
       p.name
         ^

scala> p.getName
Alvin Alexander

定義輔助構造函數
在類內部以this爲名的方法定義輔助構造函數,可以定義多個輔助構造函數,但這些構造函數必須有不同簽名(參數列表)。同時,每個構造函數必須調用一個之前已經定義好的構造函數。

  • 輔助構造函數必須使用this命名創建;
  • 每個輔助構造函數必須從調用之前定義的構造函數開始;
  • 每個構造函數必須要有不同的簽名;
  • 一個構造函數通過this調用另一個不同的構造函數。

注意:一個輔助構造函數只需要調用之前定義過的構造函數就可以了。

// primary contructor
class Pizza(var crustSize: Int, var crustType: String) {
  // one-arg auxiliary constructor
  def this(crustSize: Int){
    this(crustSize, Pizza.DEFAULT_CRUST_TYPE)
  }

  // one-arg auxiliary constructor
  def this(crustType: String){
    this(Pizza.DEFAULT_CRUST_SIZE, crustType)
  }

  // zero-arg auxiliary constructor
  def this(){
    this(Pizza.DEFAULT_CRUST_SIZE, Pizza.DEFAULT_CRUST_TYPE)
  }

  override def toString: String = s"A $crustSize inch pizza with a $crustType crust"

  object Pizza{
    val DEFAULT_CRUST_SIZE = 12
    val DEFAULT_CRUST_TYPE = "THIN"
  }
}

定義一個私有的主構造函數
在使用單例模式時,需要創建一個私有的主構造函數。
在類名和構造函數接收的任意參數之間插入一個private關鍵字,就可以創建私有主構造函數。

// 私有的主構造函數
class Brain private{
  override def toString: String = "This is the brain"
}

object Brain {
  val brain = new Brain
  // 在類的伴生對象中實現一個getInstance方法
  def getInstance = brain
}

object SingletonTest extends App{
  val brain = Brain.getInstance
  println(brain)
}

伴生對象:一個伴生對象就是定義在與類的同一個文件中,同時與類有相同的名字的對象。


設置構造函數參數的默認值

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章