What can an `object` declaration do that constructors-and-classes can't, and where can object declarations be placed (top-level vs nested)? Cover interface implementation, inheritance, and nesting.
answer
- Implements interfaces, extends one open class
- No constructor; can't be subclassed or `open`/`inner`
- Top-level OR nested (Outer.Nested), still one global instance
- Nested object != tied to an outer instance
- Use for stateless strategies, sentinels, comparators
basics
~20 sAn object can be declared at the top level or nested inside a class. It can implement interfaces and extend a class, but it can't have a constructor. A nested object is still a single shared instance.
solid answer
~40 sAn `object` declaration is a full type with one instance. It **can implement interfaces and extend one open class**, so it serves as a ready-made singleton implementation (e.g., a default `Comparator`, an empty/no-op strategy). It **cannot have constructors or constructor parameters**, and you can't subclass it (no instances to vary). Placement: it can be **top-level** or **nested inside a class** (a nested `object` is accessed as `Outer.Nested` and is still a singleton, independent of any outer instance). It can also be declared as a `private`/`internal` member to scope visibility. Unlike an inner class, a nested object holds no reference to an enclosing instance. Common uses: stateless strategy/policy implementations, sentinel/empty values, registries, and `Comparator`/`Comparable` helpers — all benefiting from lazy thread-safe init.
code
kotlin · 13 linesinterface RetryPolicy { fun shouldRetry(attempt: Int): Boolean }
object NoRetry : RetryPolicy { // top-level singleton impl
override fun shouldRetry(attempt: Int) = false
}
class Client {
object Defaults { // nested singleton
val policy: RetryPolicy = NoRetry
}
}
val p = Client.Defaults.policy // accessed via class name, no Client instancego deeper
Knows an object can implement an interface and be used as a singleton.
Knows it can extend one class and be nested, accessed via the class name.
Explains nested-object independence from outer instance, the no-inner/no-subclass rules, and idiomatic uses.
Chooses singleton-object designs (sentinels, stateless strategies) deliberately and distinguishes them cleanly from companions and object expressions.
## Capabilities of an object declaration ### Implements interfaces An object can satisfy an interface, giving you a singleton implementation with no boilerplate: ```kotlin val byLength = object : Comparator<String> { /* anonymous */ } // but as a *named singleton*: object LengthComparator : Comparator<String> { override fun compare(a: String, b: String) = a.length - b.length } listOf("bb", "a").sortedWith(LengthComparator) ``` ### Extends one open class It can extend a single open class (Kotlin is single-inheritance for classes): ```kotlin open class BaseHandler { open fun handle() {} } object DefaultHandler : BaseHandler() ``` ### What it CANNOT do - **No constructor / no parameters** — there is one fixed instance. - **Cannot be subclassed / cannot be `open`** as an object — there are no varying instances. - It is effectively final. ## Placement ### Top-level Most objects sit at file top level: `object AppConfig { ... }`. ### Nested in a class An object can be declared inside a class and is reached through the class name: ```kotlin class Repository { object Defaults { // nested object declaration const val PAGE_SIZE = 20 } } val n = Repository.Defaults.PAGE_SIZE ``` Key point: a **nested object is independent of any `Repository` instance** — it is one global singleton, *not* tied to an outer object. (This is unlike an `inner class`, which holds a reference to its enclosing instance; objects cannot be `inner`.) ### Visibility scoping Objects honor visibility modifiers: `private object`, `internal object`, etc., to limit who can see the singleton. ## Typical use cases - **Stateless strategy/policy:** a singleton implementing a `Strategy` interface. - **Sentinel / empty value:** `object EmptyResult : Result`. - **Comparators / orderings.** - **Registries** of immutable data. - **No-op implementations** of a callback interface. All inherit the lazy, thread-safe, exactly-once initialization of object declarations. ## Note on the boundary This leaf is the *named singleton* `object Name`. Two related forms are out of scope here: `companion object` (a singleton tied to a class for factory/static-like members) and *object expressions* (`object : T { }`, anonymous, possibly many instances). They share the keyword but serve different roles. ## Keywords/APIs to name `object`, interface implementation via `: Interface`, single-class inheritance `: OpenClass()`, `private`/`internal object`, contrast with `inner class`, and `Comparator`/`Comparable`.
- Can an object declaration be `inner`?No. `inner` requires a reference to an enclosing instance; an object is a single global instance and has no enclosing-instance link.
- Can you subclass an `object`?No. It is effectively final — there's exactly one instance, so there's nothing to vary via subclassing.
saying these in an interview costs you the question
- Saying a nested object is tied to / scoped per outer instance
- Claiming an object can be `inner` or `open`/subclassed
- Thinking an object can extend multiple classes
- Conflating the named `object` with companion object or object expression