Scala學習之類和屬性篇(一):定義類的主構造方法

在Scala中直接在類名後面跟上參數,便可定義類的主構造方法。es6

scala> :paste
// Entering paste mode (ctrl-D to finish)

class Person(var firstName: String, var lastName:String) {
  println("The construct begins.")
  var age = 18
  println(this)
  println("The construct ends.")
  override def toString = s"$firstName $lastName is $age years old."
}

// Exiting paste mode, now interpreting.

defined class Person

接下來咱們經過主構造方法來實例化這個類,看看發生了什麼。全部定義在類體內部的可執行性代碼都被執行了,也就是說整個類內部都是這個主構造方法的方法體。ide

scala> val p = new Person("wang", "wei")
The construct begins.
wang wei is 18 years old.
The construct ends.
p: Person = wang wei is 18 years old.

至此,主構造方法的參數和方法體部分都已經說明了。this

接下來咱們嘗試訪問一下類的幾個屬性,你會發現能夠直接用類名加屬性名來訪問。es5

scala> p.firstName
res4: String = wang

scala> p.lastName
res5: String = wei

scala> p.age
res6: Int = 18

因爲全部屬性都是使用var關鍵字來定義的,因此咱們能夠改變他們的值。scala

scala> p.firstName = "Li"
p.firstName: String = Li

scala> p.lastName = "Ming"
p.lastName: String = Ming

scala> p.age = 20
p.age: Int = 20

scala> println(p)
Li Ming is 20 years old.

接下來咱們討論一下主構造方法中參數的可見性問題。code

使用var修飾的主構造方法參數,由於是可變的全部Scala會自動爲其生成get和set方法。get

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

scala> val p = new Person("Ming");
p: Person = Person@25d3cfc8

scala> p.name
res8: String = Ming

scala> p.name = "Ning"
p.name: String = Ning

scala> p.name
res9: String = Ning

使用val修飾的主構造方法參數,由於是不可變的全部Scala不會爲其生成set方法。it

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

scala> val p = new Person("Ming")
p: Person = Person@5edc70ed

scala> p.name
res10: String = Ming

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

不適用val或者var關鍵字修飾的主構造方法參數,Scala將採起最嚴格的訪問限制,set和get方法都不會被提供,而且這個參數是不可變的。console

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

scala> val p = new Person("Ming")
p: Person = Person@36aa52d2

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

scala> p.name = "Ning"
<console>:15: error: value name is not a member of Person
val $ires8 = p.name
               ^
<console>:13: error: value name is not a member of Person
       p.name = "Ning"
         ^

若是強行爲無關鍵字修飾的主構造方法參數添改變其值的方法,會致使編譯報錯。編譯

scala> :paste
// Entering paste mode (ctrl-D to finish)

class Person(name: String) {
  def getName = println(name)
  def setName(_name: String) { this.name = _name }
}

// Exiting paste mode, now interpreting.

<console>:13: error: reassignment to val
         def setName(_name: String) { this.name = _name }
                                                ^

在val或者var關鍵字前面加上private關鍵字,那麼Scala一樣不會爲這個參數生成get和set方法。那麼咱們若是想定義一個可變但不可訪問的參數該怎麼辦呢:private var argument。這樣Scala不會爲其生成set和get方法,可是你能夠在類的內部自定義一些方法來改變這個參數的值。

scala> :paste
// Entering paste mode (ctrl-D to finish)

class Person(private var name: String) {
  def printName = println(name)
  def setName(_name: String) { this.name = _name }
}

// Exiting paste mode, now interpreting.

defined class Person

scala> val p = new Person("Ming")
p: Person = Person@5d342959

scala> p.printName
Ming

scala> p.setName("Ning")

scala> p.printName
Ning

總結:主構造方法參數可見性一共有這麼幾種

  • 使用var修飾:Scala會爲其生成get和set方法。
  • 使用val修飾:Scala會爲其生成get方法。
  • 不使用修飾:Scala不會爲其生成get和set方法,而且參數值不可改變。(效果等同於private val)
  • 使用private修飾:Scala不會爲其生成get和set方法,但參數可變性由var和val來決定。

注意:使用case class來定義的類的主構造方法參數,若是你不適用任何修飾默認使用val修飾。

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

scala> val p = new Person("Ming")
p: Person = Person(Ming)

scala> p.name
res15: String = Ming

scala> p.name = "Ning"
<console>:14: error: reassignment to val
       p.name = "Ning"
              ^
相關文章
相關標籤/搜索