# Composition vs Inheritance

URL: https://softwaredictionary.org/compare/composition-vs-inheritance
Last updated: 2026-10-06

In short: Composition reuses code by holding other objects and delegating to them (has-a); inheritance reuses it by extending a parent class (is-a).

## What is the difference between composition and inheritance?

Composition and inheritance are the two main ways to reuse code in object-oriented programming. Composition builds a class from other objects that it holds in fields and delegates work to, modeling a has-a relationship: a `Car` has an `Engine`. Inheritance creates a new class from an existing one, which gets the parent's fields and methods and can override them, modeling an is-a relationship: a `Dog` is an `Animal`.

The essential difference is coupling. A subclass depends on its parent's internals, so a change in the parent can break every child, and the hierarchy is fixed when the code is written; when features combine, subclasses multiply into `ElectricCar`, `HybridCar` and `SelfDrivingElectricCar`. With composition, the parts usually sit behind interfaces, so they can be chosen at runtime, swapped, or replaced by fakes in tests. The cost is a little more code, since each delegating method has to be written.

"Favor object composition over class inheritance" comes from the 1994 book Design Patterns by the Gang of Four, and patterns such as strategy, decorator and dependency injection are built on it. It is a preference, not a ban: inheritance remains the right tool for true is-a relationships, such as a custom error type that extends `Error`, and most real designs use both, inheriting from a small base class or implementing an interface and composing the rest. Some languages lean toward composition by design: Go has no class inheritance and embeds structs instead, and Kotlin delegates a whole interface to a field with `by`.

A common misconception is that inheritance is needed for polymorphism. Interfaces give the same ability to treat different objects alike, without sharing code. Another is that inheritance is a good way to reuse a handy method; extending a class only for its code creates the tight coupling that composition avoids. The simple test is one question: is it a kind of X, or does it have or use an X?

| Aspect | Composition | Inheritance |
| --- | --- | --- |
| Relationship | has-a: a car has an engine | is-a: a dog is an animal |
| How code is reused | By delegating calls to objects held in fields | By inheriting fields and methods from a parent class |
| Coupling | Loose: depends only on the parts' interfaces | Tight: a subclass depends on its parent's internals |
| When it is fixed | Parts can be chosen at runtime or swapped in tests | Fixed when the class is written |
| Combining features | Mix parts freely, such as an engine and a driver | Each combination may need its own subclass |
| Amount of code | More: each delegating method is written out | Less: inherited methods come for free |
| Polymorphism | Through shared interfaces | Through overriding the parent's methods |
| Language support | Every language; Go and Kotlin add built-in help | Most OOP languages; Go has no class inheritance |

## Choose Composition when

- One object has or uses another, such as a car and its engine.
- Behavior should be swappable at runtime or replaced with a fake in tests.
- Features combine in many ways that would multiply subclasses.
- You want to reuse a class you don't control without depending on its internals.

## Choose Inheritance when

- One type truly is a kind of another and can be used wherever the parent is expected.
- A framework expects you to extend its base class, such as `Error` or a UI component class.
- The hierarchy is shallow and stable, and subclasses share most of the parent's code.

## Frequently asked questions

**What does "composition over inheritance" mean?**

It is a design guideline: to reuse behavior, prefer holding an object that provides it over extending a class that has it. Inheritance isn't forbidden; it is kept for true is-a relationships.

**Is inheritance bad?**

No. It is the right tool when one type truly is a kind of another and the hierarchy stays shallow. The trouble comes from deep trees and from inheriting only to reuse code.

**How does Go work without inheritance?**

Go has no classes. It embeds one struct in another, which makes the embedded type's methods available on the outer one, and uses interfaces for polymorphism, so reuse happens through composition.

---

Software Dictionary: https://softwaredictionary.org/ · https://softwaredictionary.org/llms.txt
