skip to content

How do you implement a Factory interface on a companion object, and why is that useful?

level: middleimportance: should knowfreq 45%

answer

  1. companion object : Factory<T>
  2. companion is a real object → can implement interfaces
  3. pass ClassName.Companion as a Factory value
  4. registries / DI without reflection
  5. Factory<out T> enables variance

basics

~20 s

A companion object is a real object, so it can implement an interface. You write companion object : Factory<T> and override the interface's create function. Now the class's companion can be passed around as a Factory value.

solid answer

~40 s

Because a `companion object` is an actual object instance (not just static slots), it can extend a superclass or implement interfaces. You declare `companion object : Factory<MyType> { override fun create(...) = MyType(...) }`. This means the companion itself is a value of type `Factory<MyType>`, so you can pass `MyType.Companion` (or `MyType` where the companion is implied) wherever a `Factory<MyType>` is expected — useful for plugging classes into generic creation frameworks, registries, or dependency-injection wiring without reflection. The interface gives a uniform, type-safe `create` contract across many types, and each class supplies its own construction logic in its companion. You can reference the companion explicitly as `MyType.Companion` or by the class name when context expects the companion.

code

kotlin · 12 lines
kotlin
interface Factory<out T> { fun create(): T }

class Widget private constructor(val n: Int) {
    companion object : Factory<Widget> {
        private var next = 0
        override fun create(): Widget = Widget(next++)
    }
}

fun <T> repeatCreate(f: Factory<T>, times: Int) = (1..times).map { f.create() }

val widgets = repeatCreate(Widget, 3) // Widget.Companion passed as Factory<Widget>

go deeper

for a junior

Recognizes the companion object : Interface syntax and that you override the interface method.

for a middle

Explains that the companion is a real object passable as the interface type and gives a registry/DI use case.

for a senior

Adds variance (out T), combines interface hook with named factories, and discusses reflection-free plugin registries.

for a principal

Designs an extensible creation SPI where companions register as factories, weighing variance, binary compatibility, and discoverability trade-offs.

## The key fact A Kotlin `companion object` is a genuine singleton **object instance** attached to the class — not merely Java-style static members. Therefore it can do everything an object can: implement interfaces and extend an open class. ## Defining a Factory interface and implementing it ```kotlin interface Factory<out T> { fun create(): T } class Connection private constructor(val id: Int) { companion object : Factory<Connection> { private var counter = 0 override fun create(): Connection = Connection(counter++) } } ``` Now `Connection.Companion` is a `Factory<Connection>`. You can store it, pass it, and call it polymorphically: ```kotlin fun <T> buildTwo(factory: Factory<T>): List<T> = listOf(factory.create(), factory.create()) val conns = buildTwo(Connection) // companion is passed as the Factory ``` When the expected type is the companion's interface, you can pass the **class name** (`Connection`) and Kotlin resolves it to `Connection.Companion`; otherwise reference it explicitly as `Connection.Companion`. ## Why this is useful - **Uniform, type-safe creation contract** across many unrelated classes — each class carries its own factory in its companion. - **Registries / plugin systems**: a `Map<String, Factory<Base>>` can map keys to companions, choosing an implementation at runtime without reflection. - **Generic frameworks / DI**: pass a companion as a creation strategy. - **`out` variance** (`Factory<out T>`) lets a `Factory<Sub>` be used as a `Factory<Super>`. ## Combining with a named factory and private constructor You can have both: an interface-driven `create()` plus extra named factories (`fromConfig(...)`) and a `private constructor` so the companion is the only construction path. The interface method gives a polymorphic hook; the named functions give ergonomic, validated entry points. ## Gotchas - The companion's interface members are part of the companion's type, accessed via the companion, not as plain static-looking calls unless the call site expects the interface. - A class has at most one companion object, so all factory interfaces it implements live on that single companion.

  • How do you reference the companion explicitly when you need it as the interface type?
    Use `ClassName.Companion`. Where the call site already expects the interface, you can pass just `ClassName` and Kotlin resolves it to the companion.
  • Can a class implement two different factory interfaces this way?
    Yes — a class has one companion, and that single companion can implement multiple interfaces, as long as their members don't conflict.

The companion acting as a Factory is like a car model's official dealership: there's exactly one per model, and it satisfies the generic 'sells cars' contract so any buyer can use it interchangeably.

saying these in an interview costs you the question

  • Saying a companion can't implement interfaces because it's 'just static'
  • Thinking you need reflection to use a class as a factory
  • Believing each factory interface needs its own companion (only one companion allowed)
  • Confusing the companion (instance) with the class itself

context