How do you make your own non-data class destructurable, and why might you deliberately add a `componentN()` operator?
answer
- Declare operator fun componentN()
- Return value can be computed, not just stored
- Extension operators add destructuring to foreign types
- componentN order is a public positional contract
- data class covers only primary-constructor props
basics
~10 sDeclare operator fun componentN() functions on the class — one per position you want to expose. They can return anything, including computed values, not just constructor properties.
solid answer
~40 sAny class becomes destructurable by declaring `operator fun component1()`, `component2()`, and so on. `data class` does this automatically for primary-constructor properties, but you can hand-write them on a regular class or via extension functions. The return value is whatever you want — a computed projection, a reformatted field, even a derived value — because the operator is just a function. This lets you control the destructuring contract independently of the class's storage. A key design subtlety: because destructuring is positional, the *order and meaning* of `componentN()` becomes part of your public API. Reordering or repurposing them silently breaks callers without a compile error. So you add custom `componentN()` only when there's a stable, obvious positional reading (like coordinates) — and avoid it for wide types where positional access is confusing.
code
kotlin · 6 linesclass Money(private val cents: Long) {
operator fun component1() = cents / 100 // whole units
operator fun component2() = cents % 100 // remaining cents
}
val (dollars, change) = Money(1099)
println("$dollars.$change") // 10.99go deeper
Knows data classes give destructuring for free but may not know how to add it manually.
Can write operator fun componentN() and knows only constructor properties are auto-generated.
Uses computed/extension component operators and explains the positional public-API contract and reordering hazard.
Sets team conventions: limit destructuring to small ordered tuples, prefer named access for wide types, and treats componentN order as a versioned contract.
## Opting a class in Destructuring requires `operator fun componentN()` functions. You can declare them in the class or as extensions: ```kotlin class Rgb(val packed: Int) { operator fun component1() = (packed shr 16) and 0xFF // red operator fun component2() = (packed shr 8) and 0xFF // green operator fun component3() = packed and 0xFF // blue } val (r, g, b) = Rgb(0x00FF8040) // r=255, g=128, b=64 ``` Notes: - They must be marked `operator`. - Return type is arbitrary; values can be **computed**, not stored. This is the main reason to write them by hand: expose a clean destructuring view over a different internal representation. - Extension operators work too, letting you add destructuring to types you don't own: ```kotlin operator fun java.time.LocalDate.component1() = year operator fun java.time.LocalDate.component2() = monthValue operator fun java.time.LocalDate.component3() = dayOfMonth val (y, m, d) = java.time.LocalDate.now() ``` ## data class vs hand-written `data class` auto-generates `componentN()` for primary-constructor properties in order. Properties declared in the body (not the constructor) are **not** included. Hand-writing gives full control but you own the maintenance. ## The design hazard: positional API Because binding is positional, `componentN()` order is a **stable public contract**: - Reordering constructor properties of a `data class` silently changes what each destructured variable receives — no compile error at call sites. - This is why the official guidance is to be cautious destructuring wide data classes; a name-based read (`p.age`) is refactor-safe, a positional read (`val (_, age) = p`) is not. ## When to add custom componentN() Good: small, conceptually ordered tuples (coordinates, color channels, ranges). Bad: large entities where positional meaning isn't obvious — it harms readability and invites reordering bugs. ## Interop `operator` is a Kotlin-only convention; Java callers just see plain methods named `component1`, etc.
- Are properties declared in a data class body (not the constructor) part of destructuring?No. Only primary-constructor properties get generated componentN(). Body properties must be exposed manually with operator functions if you want them destructurable.
- Why is reordering a data class's constructor properties risky for destructuring callers?Destructuring is positional, so reordering swaps which value each variable receives with no compile error at call sites — a silent behavioral bug.
componentN() is like numbered output ports on a device: rewiring what each port emits silently changes everything plugged into them.
saying these in an interview costs you the question
- Forgetting the `operator` keyword
- Assuming body properties of a data class are destructurable
- Adding componentN() to wide entities with no natural order
- Not recognizing positional binding as a public API contract