主構造函數
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)
}
伴生對象:一個伴生對象就是定義在與類的同一個文件中,同時與類有相同的名字的對象。
設置構造函數參數的默認值