class / Constructor
| Since: | Kotlin 1.0(2016) |
|---|
Classes in Kotlin are defined with the class keyword. You can write the primary constructor directly in the class header, and place initialization logic in an init block. Secondary constructors use the constructor keyword.
Syntax
// Primary constructor (most common form)
class Person(val name: String, var age: Int)
// Use an init block for initialization logic.
class User(val name: String, val age: Int) {
init {
require(age >= 0) { "Age must be 0 or greater" }
}
}
// Secondary constructor (constructor keyword)
class Point {
val x: Double
val y: Double
constructor(x: Double, y: Double) {
this.x = x
this.y = y
}
constructor(value: Double) : this(value, value) // delegation
}
Syntax reference
| Syntax | Description |
|---|---|
| class ClassName(val x: Type) | A primary constructor that declares properties directly. |
| init { } | An initialization block that runs when an instance is created. |
| constructor(params) { } | Defines a secondary constructor. |
| : this(args) | Delegates to another constructor. |
| private constructor | Makes the constructor private (e.g., for the factory pattern). |
Sample code
sample_class_constructor.kt
// Primary constructor with property declarations
class Person(
val name: String,
var age: Int,
val email: String = "" // default argument
) {
// The init block runs after the constructor.
init {
require(name.isNotBlank()) { "Name cannot be blank" }
require(age >= 0) { "Age must be 0 or greater" }
println("Person instance created: $name (age $age)")
}
// Computed property
val greeting: String
get() = "Hello, I'm ${name}!"
}
// Example of a secondary constructor
class Rectangle(val width: Double, val height: Double) {
val area: Double = width * height
// Secondary constructor for squares
constructor(side: Double) : this(side, side)
}
// Private constructor (factory pattern)
class Database private constructor(val url: String) {
companion object {
fun create(url: String): Database {
println("Connecting to database: $url")
return Database(url)
}
}
}
fun main() {
// Create an instance using the primary constructor
val iori = Person("Yagami Iori", 20, "yagami_iori@wp-p.info")
println(iori.greeting)
// Use the default argument.
val kyo = Person("Kusanagi Kyo", 20)
println("Kusanagi Kyo's email: '${kyo.email}'") // empty string
// Call the constructor with named arguments.
val terry = Person(name = "Terry Bogard", age = 24)
println("Terry Bogard's age: ${terry.age}")
// Secondary constructor
val rect = Rectangle(4.0, 3.0)
val square = Rectangle(5.0) // square
println("Rectangle area: ${rect.area}") // 12.0
println("Square area: ${square.area}") // 25.0
// Factory pattern
val db = Database.create("jdbc:mysql://localhost/mydb")
println("Connected to: ${db.url}")
// Validation in init (invalid arguments throw an exception)
try {
Person("", 25)
} catch (e: IllegalArgumentException) {
println("Error: ${e.message}")
}
}
class_constructor.kt
kotlinc class_constructor.kt -include-runtime -d class_constructor.jar java -jar class_constructor.jar Person instance created: Yagami Iori (age 20) Hello, I'm Yagami Iori! Person instance created: Kusanagi Kyo (age 20) Kusanagi Kyo's email: '' Person instance created: Terry Bogard (age 24) Terry Bogard's age: 24 Rectangle area: 12.0 Square area: 25.0 Connecting to database: jdbc:mysql://localhost/mydb Connected to: jdbc:mysql://localhost/mydb Error: Name cannot be blank
Common Mistakes
NG example 1: Forgetting val/var in the primary constructor means the parameters are not properties.
mistake1_no_val.kt
class Fighter(name: String, power: Int) // name and power are parameters only, not properties
fun main() {
val f = Fighter("Kusanagi Kyo", 100)
// println(f.name) // Compile error: not a property
}
Adding val/var makes them properties.
fix1_with_val.kt
class Fighter(val name: String, var power: Int)
fun main() {
val f = Fighter("Yagami Iori", 120)
println("${f.name}: ${f.power}")
}
The command looks like this:
kotlinc fix1_with_val.kt -include-runtime -d fix1_with_val.jar java -jar fix1_with_val.jar Yagami Iori: 120
NG example 2: A secondary constructor that does not delegate to the primary constructor causes a compile error.
mistake2_no_delegation.kt
class Team(val name: String) {
// Compile error: must delegate with : this(...)
// constructor(name: String, leader: String) {
// println("$name, $leader")
// }
}
Delegate with : this(...).
fix2_delegation.kt
class Team(val name: String, val leader: String = "TBD") {
constructor(name: String, leader: String, rank: Int) : this(name, leader) {
println("$name team (rank $rank), leader: $leader")
}
}
fun main() {
val team = Team("KOF", "Terry Bogard", 1)
println(team.name)
}
The command looks like this:
kotlinc fix2_delegation.kt -include-runtime -d fix2_delegation.jar java -jar fix2_delegation.jar KOF team (rank 1), leader: Terry Bogard KOF
NG example 3: A parameter without val/var is accessible in init blocks but not in methods.
mistake3_no_property.kt
class Hero(name: String) {
init {
println("init: $name") // Accessible inside init
}
// fun greet() = println("Hello, $name!") // Compile error: unresolved reference
}
Store it as a property with val.
fix3_val_property.kt
class Hero(val name: String) {
init {
println("init: $name")
}
fun greet() = println("Hello, $name!")
}
fun main() {
val hero = Hero("King")
hero.greet()
}
The command looks like this:
kotlinc fix3_val_property.kt -include-runtime -d fix3_val_property.jar java -jar fix3_val_property.jar init: King Hello, King!
Notes
Kotlin classes are far more concise than their Java equivalents when it comes to constructors. Because you can declare properties directly in the primary constructor, the field declaration, constructor body, and assignment that Java requires are all condensed into a single line.
You can write multiple init blocks; they are executed in order from top to bottom. A secondary constructor must always delegate to the primary constructor using : this(...).
For classes focused purely on holding data, see data class. For inheritance and overriding, see open / override.
If you find any errors or copyright issues, please contact us.