构造函数

主构造函数

在 Scala 中,主构造函数是类的主体。类名后跟一个参数列表,它们是构造函数参数。 (与任何函数一样,可以省略空参数列表。)

class Foo(x: Int, y: String) {
    val xy: String = y * x
    /* now xy is a public member of the class */
}

class Bar {
    ...
}

除非通过 val 关键字标记为实例成员,否则实例的构造参数不能在其构造函数体外部访问:

class Baz(val z: String) 
// Baz has no other members or methods, so the body may be omitted

val foo = new Foo(4, "ab")
val baz = new Baz("I am a baz")
foo.x // will not compile: x is not a member of Foo
foo.xy // returns "abababab": xy is a member of Foo
baz.z // returns "I am a baz": z is a member of Baz
val bar0 = new Bar
val bar1 = new Bar() // Constructor parentheses are optional here

实例化对象实例时应执行的任何操作都直接写在类的主体中:

class DatabaseConnection
    (host: String, port: Int, username: String, password: String) {
    /* first connect to the DB, or throw an exception */
    private val driver = new AwesomeDB.Driver()
    driver.connect(host, port, username, password)
    def isConnected: Boolean = driver.isConnected
    ...
}

请注意,将尽可能少的副作用放入构造函数中被认为是一种好习惯; 应该考虑使用 connectdisconnect 方法而不是上面的代码,以便消费者代码负责调度 IO。

辅助构造器

类可能有其他构造函数称为辅助构造函数。这些是由 def this(…) = e 形式的构造函数定义定义的,其中 e 必须调用另一个构造函数:

class Person(val fullName: String) {    
  def this(firstName: String, lastName: String) = this(s"$firstName $lastName")
}

// usage:
new Person("Grace Hopper").fullName // returns Grace Hopper
new Person("Grace", "Hopper").fullName // returns Grace Hopper

这意味着每个构造函数都可以有一个不同的修饰符:只有一些可以公开使用:

class Person private(val fullName: String) {    
  def this(firstName: String, lastName: String) = this(s"$firstName $lastName")
}

new Person("Ada Lovelace") // won't compile
new Person("Ada", "Lovelace") // compiles

通过这种方式,你可以控制使用者代码如何实例化该类。