在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
总结:主构造方法参数可见性一共有这么几种
注意:使用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" ^