kotlinintermediate
Class Delegation with by Keyword
Use Kotlin's 'by' keyword for class delegation: interface forwarding, decorated behavior, and composition.
kotlinPress ⌘/Ctrl + Shift + C to copy
interface Repository<T> {
fun findAll(): List<T>
fun findById(id: String): T?
fun save(item: T): T
fun delete(id: String): Boolean
}
class InMemoryRepository<T>(private val idOf: (T) -> String) : Repository<T> {
private val store = mutableMapOf<String, T>()
override fun findAll() = store.values.toList()
override fun findById(id: String) = store[id]
override fun save(item: T): T { store[idOf(item)] = item; return item }
override fun delete(id: String) = store.remove(id) != null
}
// Logging decorator via delegation
class LoggingRepository<T>(
private val delegate: Repository<T>
) : Repository<T> by delegate {
override fun save(item: T): T {
println("[LOG] Saving: $item")
return delegate.save(item)
}
override fun delete(id: String): Boolean {
println("[LOG] Deleting: $id")
return delegate.delete(id)
}
}
// Caching decorator
class CachingRepository<T>(
private val delegate: Repository<T>
) : Repository<T> by delegate {
private var cache: List<T>? = null
override fun findAll(): List<T> = cache ?: delegate.findAll().also { cache = it }
override fun save(item: T): T { cache = null; return delegate.save(item) }
}
// Multiple interface delegation
interface Printer { fun print(doc: String) }
interface Scanner { fun scan(): String }
class SimplePrinter : Printer {
override fun print(doc: String) = println("Printing: $doc")
}
class SimpleScanner : Scanner {
override fun scan() = "Scanned document content"
}
class AllInOne(
printer: Printer, scanner: Scanner
) : Printer by printer, Scanner by scanner
data class Task(val id: String, val title: String)
fun main() {
val repo: Repository<Task> = CachingRepository(
LoggingRepository(InMemoryRepository { it.id })
)
repo.save(Task("1", "Buy groceries"))
repo.save(Task("2", "Write code"))
println("All: ${repo.findAll()}")
println("All: ${repo.findAll()}") // from cache
val device = AllInOne(SimplePrinter(), SimpleScanner())
device.print("Hello")
println("Scanned: ${device.scan()}")
}Use Cases
- Decorator pattern with minimal boilerplate
- Composing behavior from multiple interfaces
- Transparent caching and logging layers
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
kotlinintermediate
Delegation — by, lazy, observable, and Custom
Use Kotlin delegation for reusable behavior: by keyword, lazy, observable, vetoable, and map-backed.
Best for: Composing behavior without deep inheritance
#kotlin#delegation
kotlinintermediate
Interface Delegation with 'by'
Delegate interface implementations with the 'by' keyword: composition over inheritance patterns.
Best for: Composition over inheritance
#kotlin#delegation
kotlinintermediate
Map Delegation for Dynamic Properties
Delegate properties to maps: dynamic configuration, JSON-to-object mapping, and flexible data classes.
Best for: Dynamic configuration loading
#kotlin#delegation
kotlinbeginner
Delegate Properties to a Map
Store class properties in a map using Kotlin delegation for dynamic and flexible data objects.
Best for: Dynamic configuration from external sources
#kotlin#delegation