Exercise: Lateinit delegate
Implement a Lateinit
delegate that makes a property behave like a lateinit
property so that the delegate can keep set values, but it should not require an initial value. If the getter is called before the property is set, it should throw an IllegalStateException
exception with the message "Uninitialized lateinit property {name}".
val a by Lateinit<Int>()
a = 1
println(a) // 1
val b by Lateinit<String>()
b = "ABC"
println(b) // ABC
val c by Lateinit<String>()
println(c) // IllegalStateException:
// Uninitialized lateinit property c
This delegate should support nullable types.
val a by Lateinit<Int?>()
a = 1
println(a) // 1
a = null
println(a) // null
This problem can either be solved in the below playground or you can clone kotlin-exercises project and solve it locally. In the project, you can find code template for this exercise in advanced/delegates/Lateinit.kt. You can find there unit tests.
Hint: You can make your class implement the ReadWriteProperty<Any?, T>
interface to make it a property delegate.
Once you are done with the exercise, you can check your solution here.
import org.junit.Test
import kotlin.properties.Delegates
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
import kotlin.test.assertEquals
import kotlin.test.assertIs
// TODO
// Implement Lateinit delegate here
// Easy: Uncomment the first 2 tests and implement Lateinit so it works for Int type
// Medium: Uncomment the first 3 tests and implement Lateinit so it works for all non-nullable types
// Hard: Uncomment all tests and implement Lateinit so it works for all types
class LateinitTest {
@Test
fun `Throws exception if accessed before initialization`() {
var value: Int by Lateinit()
val res = runCatching {
println(value)
}
val exception = assertIs<IllegalStateException>(res.exceptionOrNull())
assertEquals("Uninitialized lateinit property value", exception.message)
var value2: Int by Lateinit()
val res2 = runCatching {
println(value2)
}
val exception2 = assertIs<IllegalStateException>(res2.exceptionOrNull())
assertEquals("Uninitialized lateinit property value2", exception2.message)
}
@Test
fun `Behaves like a normal variable for Int`() {
var value: Int by Lateinit()
value = 10
assertEquals(10, value)
value = 20
assertEquals(20, value)
}
@Test
fun `Behaves like a normal variable for String`() {
var value: String by Lateinit()
value = "AAA"
assertEquals("AAA", value)
value = "BBB"
assertEquals("BBB", value)
}
@Test
fun `Behaves like a normal variable for nullable String`() {
var value: String? by Lateinit()
value = "AAA"
assertEquals("AAA", value)
value = null
assertEquals(null, value)
value = "BBB"
assertEquals("BBB", value)
}
}
Marcin Moskala is a highly experienced developer and Kotlin instructor as the founder of Kt. Academy, an official JetBrains partner specializing in Kotlin training, Google Developers Expert, known for his significant contributions to the Kotlin community. Moskala is the author of several widely recognized books, including "Effective Kotlin," "Kotlin Coroutines," "Functional Kotlin," "Advanced Kotlin," "Kotlin Essentials," and "Android Development with Kotlin."
Beyond his literary achievements, Moskala is the author of the largest Medium publication dedicated to Kotlin. As a respected speaker, he has been invited to share his insights at numerous programming conferences, including events such as Droidcon and the prestigious Kotlin Conf, the premier conference dedicated to the Kotlin programming language.