When should you prefer a function-type alias over a `fun interface` (SAM) for a callback, and what are the trade-offs?
answer
- alias = nickname, fun interface = real type
- interface gives nominal identity + defaults
- alias zero-cost, SAM may allocate
- overload/`is` only with fun interface
- Java sees fun interface, not alias
basics
~20 sUse a typealias when you only want a readable name for a lambda signature with no extra behavior. Use a fun interface when you need a real distinct type, default methods, or nominal type safety. The alias is just a name; the interface is a true type.
solid answer
~50 sA function-type alias (`typealias OnClick = (View) -> Unit`) is a compile-time nickname: zero runtime type, interchangeable with the raw function type, but no nominal identity, no members, and no way to add default methods or named parameters. A `fun interface OnClick { fun invoke(v: View) }` is a real nominal type: it can have default/extra methods, distinguishes itself from other interfaces with the same shape, supports `is` checks, and still allows lambda (SAM) construction. Prefer the alias for purely internal readability of common signatures (predicates, reducers). Prefer the `fun interface` when the callback is a public API contract you want to evolve, when you need overload resolution by type, default behavior, or distinct types for two same-shaped callbacks. Trade-off: `fun interface` allocates an object per SAM conversion (unless inlined), while an alias is free.
code
kotlin · 10 lines// Same shape, different intent — aliases can't keep them apart:
typealias OnClick = (View) -> Unit
typealias OnLongClick = (View) -> Unit // == OnClick, interchangeable!
// fun interface keeps them distinct:
fun interface Click { fun on(v: View) }
fun interface LongClick { fun on(v: View) }
fun set(c: Click) {}
// set(LongClick { }) // compile error: distinct nominal typesgo deeper
Knows both let you pass a lambda for a callback.
Can state that fun interface is a real type with possible default methods while an alias is just a name.
Weighs nominal identity, overloads, defaults, Java interop, and SAM allocation cost to pick correctly.
Sets team guidance: aliases for internal readability, fun interfaces for public evolvable contracts; considers performance and interop.
## The two tools **Function-type alias** — `typealias` naming a function type: ```kotlin typealias OnClick = (View) -> Unit ``` A pure compile-time alias. It expands to `(View) -> Unit` (`Function1<View, Unit>`). No new type, no members, no runtime presence. **Functional interface (`fun interface`)** — a SAM interface with exactly one abstract method: ```kotlin fun interface OnClick { fun onClick(view: View) fun describe(): String = "click handler" // default method allowed } ``` A real **nominal type**. SAM conversion lets you still pass a lambda: `setListener(OnClick { v -> ... })` or, in a SAM-conversion position, just `{ v -> ... }`. ## Decision factors - **Nominal identity / type safety.** Two aliases that both expand to `(View) -> Unit` are *the same* type and freely mixed. Two `fun interface`s of identical shape are *different* types — the compiler stops you from passing one where the other is required. Choose the interface when distinct callbacks must not be confused (e.g., `OnClick` vs `OnLongClick`). - **Members / defaults.** Only a `fun interface` can carry extra or default methods, constants, or named, documented parameters. An alias has none. - **Overload resolution.** You can overload a function by two different `fun interface` types; you cannot overload by two aliases of the same underlying type. - **`is`/`as` checks & reflection.** A `fun interface` produces a checkable type; an alias does not. - **Performance.** A SAM conversion to a `fun interface` typically allocates an adapter object (unless the call site is `inline`). An alias has zero runtime cost. For hot paths or high-frequency callbacks, an alias (or `inline` higher-order function) avoids allocations. - **Java interop.** A `fun interface` is a real interface visible to Java; an alias is invisible to Java callers (they see `Function1`). ## Rule of thumb - Internal, ubiquitous signatures where readability is the only goal → **alias**. - Public, evolvable API contracts; need distinct types, defaults, named params, or Java interop → **fun interface**. ```kotlin // Alias: just readability typealias Validator<T> = (T) -> Boolean // fun interface: distinct nominal type + default method + Java-visible fun interface Validator2<T> { fun validate(value: T): Boolean fun negate(): Validator2<T> = Validator2 { !validate(it) } } ```
- Does a SAM conversion to a fun interface allocate?Usually yes — an adapter object is created per conversion, unless the receiving higher-order function is `inline`, which can elide it.
- Can you overload a function on two type aliases of the same function type?No. They're the same type, so it's a conflicting-overload error. Two distinct fun interfaces would work.
An alias is a sticky note relabeling an existing box; a fun interface is a new, labeled box you can put extra compartments in.
saying these in an interview costs you the question
- Saying aliases and fun interfaces are equivalent in type safety
- Claiming a typealias can have default methods
- Believing aliases are visible as real types to Java callers
- Ignoring SAM allocation cost when recommending fun interface for hot paths
- Thinking you can overload by two same-shaped aliases