Secondary Constructors
Part of the Object Oriented Programming section of Coddy's Kotlin journey. Lesson 5 of 57.
A class can offer extra ways of being created with secondary constructors, declared with constructor. Each one must call the primary constructor with this(...):
class Temperature(val celsius: Double) {
constructor(fahrenheit: Int) : this((fahrenheit - 32) * 5 / 9.0)
}Inside main:
println(Temperature(20.0).celsius)
println(Temperature(212).celsius)Output:
20.0
100.0Default arguments often make secondary constructors unnecessary. Prefer one primary constructor with defaults, and use a secondary constructor when the input has a different shape, such as text to parse:
class Color(val r: Int, val g: Int, val b: Int) {
constructor(gray: Int) : this(gray, gray, gray)
constructor(hex: String) : this(hex.substring(0, 2).toInt(16), hex.substring(2, 4).toInt(16), hex.substring(4, 6).toInt(16))
fun label() = "rgb($r, $g, $b)"
}Inside main:
println(Color(128).label())
println(Color("FF8000").label())Output:
rgb(128, 128, 128)
rgb(255, 128, 0)The primary constructor and its init blocks run first, then the body of the secondary constructor:
class Log(val name: String) {
init { println("primary: $name") }
constructor(id: Int) : this("log-$id") {
println("secondary: $id")
}
}Inside main:
Log(7)Output:
primary: log-7
secondary: 7Constructors must work with every overload unambiguously. Two constructors with the same parameter types are not allowed, and a call that could match several constructors does not compile.
class Size(val w: Int, val h: Int) {
constructor(side: Int) : this(side, side) // Size(3) -> a square
// constructor(w: Int) : this(w, 1) // error: same signature as above
}Challenge
EasyComplete the class Duration(val seconds: Int) with a secondary constructor (minutes: Int, seconds: Int) and another one that takes text like 1:30 or 2:05:10 (hours:minutes:seconds). Add format(), which returns h:mm:ss with two-digit minutes and seconds.
The supplied code reads durations as text with one or two colons, creates each with the text constructor and prints format(), then prints total and the formatted sum.
Your code goes in Duration.kt. Main.kt holds the supplied input/output code and cannot be edited.
Try it yourself
fun main() {
// Supplied input/output code: keep it as it is
val input = generateSequence(::readLine).toList()
var total = 0
for (line in input) {
val d = Duration(line)
println(d.format())
total += d.seconds
}
println("total " + Duration(total).format())
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Classes and Objects
Working With FilesDefining ClassesPrimary Constructorsinit Blocks and ValidationSecondary ConstructorsRecap - Library Card4Inheritance
Open Classes and SubclassesOverriding Memberssuper and ConstructorsAbstract ClassesRecap - Staff Directory2Properties and Encapsulation
Custom AccessorsVisibility ModifiersPrivate Setterslazy and lateinitRecap - Bank Account5Interfaces
Declaring InterfacesDefault MethodsMultiple InterfacesInterfaces as TypesRecap - Payment Methods8Generics
Generic FunctionsGeneric ClassesType ConstraintsVariance With in and outRecap - Priority Queue11Project: Library Management
Books and MembersBorrowing BooksPractice on your own: Kotlin playground