The primary constructor is considered the default way to instantiate a class, but we can define secondary constructors as well to provide alternative ways to create a class instance. The following code shows how to add a secondary constructor to our School class:
class School {
var name = ""
constructor(schoolName: String) {
name = schoolName
}
}
To add a secondary constructor, we can use the constructor keyword within the class body to define the new constructor logic. In this example, we've added a secondary constructor that takes a schoolName parameter to be assigned to the name property.
If a class has a primary constructor, then any secondary constructors must delegate to the primary constructor before any new initialization logic is run. Using our Student class as an example, we can see what this looks like:
class Student (_firstName: String, val lastName: String) {
...
constructor() : this("", "") {
// initialization logic
}
...
}
We've added a secondary constructor in the same way, but after the constructor's parameter list, we call the class's primary constructor. To do this, we must pass in any required parameter values to satisfy the primary constructor. In the Student example, this means a secondary constructor will have to supply values for _firstName and lastName when calling into the primary constructor.
When calling into the primary constructor, it's possible to access the arguments passed into the newly defined secondary constructor, as follows:
class Student (_firstName: String, val lastName: String) {
...
constructor() : this("", "") {
// initialization logic
}
constructor(_firstName: String) : this(_firstName, "") {
// initialization logic
}
...
}
This allows us to control which parameters are exposed in our constructor and to rely on sensible defaults for any primary constructor parameters we don't want to expose directly.
While secondary constructors do provide additional freedom to provide multiple paths towards instantiating a class, you may be able to avoid defining secondary constructors by making use of named arguments and default parameter values. If you commonly use secondary constructors to provide default argument values or reorder parameters, you might consider whether or not you could make use of a single primary constructor with default parameter values and named arguments.
While we can expose as many constructors as we want, sometimes we would prefer not to expose any public constructors to better control how our classes are instantiated. To enable this, we'll explore private constructors in the next section.