Kotlin Academy · Lesson

Delegating to Members

Compose behavior.

Lesson 2 of 413 steps

Delegating to Members is a free Kotlin Academy lesson on CoddyKit. This is lesson 2 of 4. Any 3 lessons of this learning path are free to read in full — after that, CoddyKit PRO unlocks every lesson, plus hands-on practice with a built-in code editor and a 24/7 AI tutor. It is part of the Kotlin Academy learning path, and your progress syncs across the web and the CoddyKit app. The Kotlin Academy course includes 4 lessons in total.

Composing Behavior

Real objects often need to combine several capabilities. Instead of inheriting from many sources, you can delegate each capability to a dedicated member object.

Two Roles, One Class

Suppose a class should both read and write. Define two interfaces and delegate each to its own implementation.

interface Reader { fun read(): String }
interface Writer { fun write(s: String): String }

class FileReader : Reader { override fun read() = "contents" }
class FileWriter : Writer { override fun write(s: String) = "wrote " + s }

class FileIO(r: Reader, w: Writer) : Reader by r, Writer by w

fun main() {
    val io = FileIO(FileReader(), FileWriter())
    println(io.read())
    println(io.write("data"))
}

Multiple Delegates

A class can delegate several interfaces at once, each to a different member. The class composes their behaviors without inheritance.

interface Logger { fun log(m: String): String }
interface Validator { fun valid(m: String): Boolean }

class ConsoleLogger : Logger { override fun log(m: String) = "LOG: " + m }
class LengthValidator : Validator { override fun valid(m: String) = m.isNotEmpty() }

class Service(l: Logger, v: Validator) : Logger by l, Validator by v

fun main() {
    val s = Service(ConsoleLogger(), LengthValidator())
    println(s.valid("hi"))
    println(s.log("started"))
}

Delegate Stored as a Member

When you need to reference the delegate inside overrides, keep it as a constructor property. The same instance backs both the forwarding and your custom code.

interface Cache { fun get(k: String): String }

class MapCache : Cache {
    override fun get(k: String) = "value-of-" + k
}

class TracingCache(private val inner: Cache) : Cache by inner {
    override fun get(k: String): String {
        println("lookup " + k)
        return inner.get(k)
    }
}

fun main() {
    println(TracingCache(MapCache()).get("id"))
}

Mixing Delegation and Own State

A delegating class can add its own properties and methods alongside the forwarded ones, enriching the composed object.

interface Engine { fun start(): String }
class V8 : Engine { override fun start() = "vroom" }

class Car(e: Engine) : Engine by e {
    var doors = 4
    fun honk() = "beep"
}

fun main() {
    val c = Car(V8())
    println(c.start())
    println(c.honk())
    println(c.doors)
}

Swapping Implementations

Because the delegate is just a member, you can construct the same wrapper with different backing implementations, choosing behavior at runtime.

interface Notifier { fun send(msg: String): String }
class EmailNotifier : Notifier { override fun send(msg: String) = "email: " + msg }
class SmsNotifier : Notifier { override fun send(msg: String) = "sms: " + msg }

class Alerts(n: Notifier) : Notifier by n

fun main() {
    println(Alerts(EmailNotifier()).send("hi"))
    println(Alerts(SmsNotifier()).send("hi"))
}

Delegating to a Property

The expression after by can be any expression evaluated once, including a constructor call. It does not have to be a parameter.

interface Greeter { fun greet() = "hi" }
class DefaultGreeter : Greeter

class Page : Greeter by DefaultGreeter()

fun main() {
    println(Page().greet())
}

Avoiding Diamond Trouble

Multiple inheritance of behavior is impossible with classes, but delegating several interfaces to separate members sidesteps the classic diamond problem cleanly.

interface A { fun a() = "A" }
interface B { fun b() = "B" }
class AImpl : A
class BImpl : B

class Combined : A by AImpl(), B by BImpl()

fun main() {
    val c = Combined()
    println(c.a() + c.b())
}

Designing for Composition

To compose well:

  • Define small, focused interfaces
  • Provide reusable implementations
  • Delegate each role in the composing class

This keeps classes flexible and testable.

Member Delegation Recap

Delegating to member objects lets a class assemble behavior from parts. You can combine many interfaces, override selectively, swap implementations, and add your own state — all without inheritance.

Next: A Direct Comparison

You have seen how flexible delegation is. The next lesson contrasts delegation with inheritance directly, so you know when to pick each.

Quick Check

Test your understanding of delegating to members.

Recap

You learned member delegation:

  • Delegate several interfaces to separate objects
  • Override selectively and add own state
  • Swap implementations at construction
  • Avoid multiple-inheritance pitfalls

Next: delegation vs inheritance.

Free to start

Learn Kotlin with an AI tutor — free

Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.

Courses
51
Lessons
203

Frequently Asked Questions

Is the “Delegating to Members” lesson free?

Yes — any 3 lessons of the Kotlin Academy learning path, including “Delegating to Members”, are free to read in full here on the web. After that, CoddyKit PRO unlocks every lesson, plus interactive practice with a built-in code editor and a 24/7 AI tutor. The Kotlin Academy course includes 4 lessons in total.

What will I learn in “Delegating to Members”?

Compose behavior. 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, so you can start here or from the beginning and move at your own pace. This is lesson 2 of 4.

How long does the “Delegating to Members” 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

  1. The by Keyword
  2. Delegating to Members
  3. Delegation vs Inheritance
  4. Practical Patterns
← Back to Kotlin Academy