Anonymous Objects and Object Expressions
Use object expressions to create one-off implementations of interfaces.
Anonymous Objects and Object Expressions is a free Kotlin Academy lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Kotlin Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Object Expressions
An object expression creates an anonymous, one-off instance of a class or interface — Kotlin's equivalent of Java's anonymous inner classes, but more powerful.
Implementing an Interface Anonymously
Use object : Interface { ... } to create an inline implementation.
interface ClickListener {
fun onClick(): String
}
fun main() {
val listener = object : ClickListener {
override fun onClick() = "clicked!"
}
println(listener.onClick())
}Anonymous Class with State
Anonymous objects can hold state and have multiple methods.
fun main() {
val counter = object {
var count = 0
fun inc() { count++ }
fun show() = println("count = $count")
}
counter.inc(); counter.inc(); counter.inc()
counter.show()
}Anonymous Object Type
The type of an anonymous object is inferred. When declared at function level, you keep access to its custom members.
fun main() {
val pair = object {
val left = "L"
val right = "R"
}
println("${pair.left} and ${pair.right}")
}Anonymous Type Exposure
If an anonymous object is returned from a function with an inferred type, callers see only the supertype — the anonymous additions are inaccessible externally.
fun makeListener() = object {
fun greet() = "hello"
}
fun main() {
val l = makeListener()
println(l.greet()) // OK — same compilation unit
}Multiple Interfaces
An anonymous object can implement multiple interfaces in one expression.
interface Closeable { fun close() }
interface Flushable { fun flush() }
fun main() {
val resource = object : Closeable, Flushable {
override fun close() = println("closed")
override fun flush() = println("flushed")
}
resource.flush()
resource.close()
}Extending a Class
Anonymous objects can extend an open class while overriding members.
open class Animal(val name: String) {
open fun speak() = "$name makes a sound"
}
fun main() {
val pet = object : Animal("Rex") {
override fun speak() = "$name barks!"
}
println(pet.speak())
}Capturing Enclosing Variables
Anonymous objects close over variables in the enclosing scope (read and modify them) — unlike Java's requirement for final.
fun main() {
var log = mutableListOf<String>()
val recorder = object {
fun record(s: String) { log.add(s) }
}
recorder.record("event 1")
recorder.record("event 2")
println(log)
}When to Use Anonymous Objects
Use anonymous objects for one-off implementations that don't deserve their own class — typically callbacks, listeners, comparators.
fun main() {
val nums = listOf(3, 1, 4, 1, 5, 9, 2, 6)
val sorted = nums.sortedWith(object : Comparator<Int> {
override fun compare(a: Int, b: Int) = b - a // descending
})
println(sorted)
}Prefer Lambdas When Possible
If the interface has a single abstract method (SAM), a lambda is cleaner than an object expression.
fun main() {
val nums = listOf(3, 1, 4, 1, 5, 9)
// Old way:
val sorted1 = nums.sortedWith(object : Comparator<Int> {
override fun compare(a: Int, b: Int) = b - a
})
// New way — SAM conversion:
val sorted2 = nums.sortedWith(Comparator { a, b -> b - a })
println("$sorted1 / $sorted2")
}Anonymous vs Declared object
Use object Name for a named singleton. Use object : Type in an expression for a one-off anonymous instance.
// Named singleton (one instance, accessed globally)
object GlobalLogger { fun log(m: String) = println("[L] $m") }
// Anonymous (created at expression evaluation)
fun main() {
val local = object { fun hi() = "hi" }
GlobalLogger.log("hello")
println(local.hi())
}Quick Check
What syntax creates an anonymous instance implementing an interface inline?
Recap
Object expressions create one-off anonymous instances inline. They can implement interfaces, extend classes, hold state, and close over enclosing variables. Prefer lambdas for single-method interfaces; reach for object expressions when you need multiple methods or state.
Frequently asked questions
Is the “Anonymous Objects and Object Expressions” lesson free?
Yes — the full text of “Anonymous Objects and Object Expressions” is free to read here on the web, and the Kotlin Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Kotlin Academy course, upgrade to CoddyKit PRO.
What will I learn in “Anonymous Objects and Object Expressions”?
Use object expressions to create one-off implementations of interfaces. You practise Kotlin Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Kotlin Academy?
No prior experience is required. Kotlin Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Anonymous Objects and Object Expressions” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Kotlin Academy lesson?
Yes. Every Kotlin Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- object Declaration: Kotlin Singletons
- companion object: Static-like Members in Kotlin
- Anonymous Objects and Object Expressions
- Factory Methods with companion object