
Composition over inheritance (or composite reuse principle) in
object-oriented programming
Object-oriented programming (OOP) is a programming paradigm based on the concept of '' objects''. Objects can contain data (called fields, attributes or properties) and have actions they can perform (called procedures or methods and impl ...
(OOP) is the principle that classes should favor
polymorphic behavior and
code reuse
Code reuse is the practice of using existing source code to develop software instead of writing new code. ''Software reuse'' is a broader term that implies using any existing software asset to develop software instead of developing it again. An as ...
by their
composition
Composition or Compositions may refer to:
Arts and literature
*Composition (dance), practice and teaching of choreography
* Composition (language), in literature and rhetoric, producing a work in spoken tradition and written discourse, to include ...
(by containing instances of other classes that implement the desired functionality) over
inheritance
Inheritance is the practice of receiving private property, titles, debts, entitlements, privileges, rights, and obligations upon the death of an individual. The rules of inheritance differ among societies and have changed over time. Offi ...
from a base or parent class. Ideally all reuse can be achieved by assembling existing components, but in practice inheritance is often needed to make new ones. Therefore inheritance and object composition typically work hand-in-hand, as discussed in the book ''
Design Patterns
''Design Patterns: Elements of Reusable Object-Oriented Software'' (1994) is a software engineering book describing software design patterns. The book was written by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides, with a fore ...
'' (1994).
Basics
An implementation of composition over inheritance typically begins with the creation of various
interfaces
Interface or interfacing may refer to:
Academic journals
* ''Interface'' (journal), by the Electrochemical Society
* '' Interface, Journal of Applied Linguistics'', now merged with ''ITL International Journal of Applied Linguistics''
* '' Inter ...
representing the behaviors that the system must exhibit. Interfaces can facilitate
polymorphic behavior. Classes implementing the identified interfaces are built and added to business domain classes as needed. Thus, system behaviors are realized without inheritance.
In fact, business domain classes may all be base classes without any inheritance at all. Alternative implementation of system behaviors is accomplished by providing another class that implements the desired behavior interface. A class that contains a reference to an interface can support implementations of the interface—a choice that can be delayed until
runtime.
Example
Inheritance
An example in
C++ follows:
class Object
;
class Visible : public Object
;
class Solid : public Object
;
class Movable : public Object
;
Then, suppose we also have these concrete classes:
* class - which is , and
* class - which is and , but not
* class - which is and , but not
* class - which is , but neither nor
Note that multiple inheritance is dangerous if not implemented carefully because it can lead to the
diamond problem
Multiple inheritance is a feature of some object-oriented computer programming languages in which an object or class can inherit features from more than one parent object or parent class. It is distinct from single inheritance, where an object o ...
. One solution to this is to create classes such as , , , etc. for every needed combination; however, this leads to a large amount of repetitive code. C++ uses
virtual inheritance to solve the diamond problem of multiple inheritance.
Composition and interfaces
The C++ examples in this section demonstrate the principle of using composition and interfaces to achieve code reuse and polymorphism. Due to the C++ language not having a dedicated keyword to declare interfaces, the following C++ example uses inheritance from a pure
abstract base class. For most purposes, this is functionally equivalent to the interfaces provided in other languages, such as Java
and C#.
Introduce an abstract class named , with the subclasses and , which provides a means of drawing an object:
class VisibilityDelegate
;
class NotVisible : public VisibilityDelegate
;
class Visible : public VisibilityDelegate
;
Introduce an abstract class named , with the subclasses and , which provides a means of moving an object:
class UpdateDelegate
;
class NotMovable : public UpdateDelegate
;
class Movable : public UpdateDelegate
;
Introduce an abstract class named , with the subclasses and , which provides a means of colliding with an object:
class CollisionDelegate
;
class NotSolid : public CollisionDelegate
;
class Solid : public CollisionDelegate
;
Finally, introduce a class named with members to control its visibility (using a ), movability (using an ), and solidity (using a ). This class has methods which delegate to its members, e.g. simply calls a method on the :
class Object
;
Then, concrete classes would look like:
class Player : public Object
;
class Smoke : public Object
;
Benefits
To favor composition over inheritance is a design principle that gives the design higher flexibility. It is more natural to build business-domain classes out of various components than trying to find commonality between them and creating a family tree. For example, an accelerator pedal and a steering wheel share very few common
traits
Trait may refer to:
* Phenotypic trait in biology, which involve genes and characteristics of organisms
* Genotypic trait, sometimes but not always presenting as a phenotypic trait
* Personality, traits that predict an individual's behavior.
** ...
, yet both are vital components in a car. What they can do and how they can be used to benefit the car are easily defined. Composition also provides a more stable business domain in the long term as it is less prone to the quirks of the family members. In other words, it is better to compose what an object can do (''
has-a
In database design, object-oriented programming and Object-oriented design, design, has-a (has_a or has a) is a Object composition, composition relationship where one object (often called the constituted object, or part/constituent/member object) ...
'') than extend what it is (''
is-a
In knowledge representation, ontology components and ontology engineering, including for object-oriented programming and design, is-a (also written as is_a or is a) is a subsumptive relationship between abstractions (e.g., types, classes), wh ...
'').
Initial design is simplified by identifying system object behaviors in separate interfaces instead of creating a hierarchical relationship to distribute behaviors among business-domain classes via inheritance. This approach more easily accommodates future requirements changes that would otherwise require a complete restructuring of business-domain classes in the inheritance model. Additionally, it avoids problems often associated with relatively minor changes to an inheritance-based model that includes several generations of classes.
Composition relation is more flexible as it may be changed on runtime, while sub-typing relations are static and need recompilation in many languages.
Some languages, notably
Go and
Rust
Rust is an iron oxide, a usually reddish-brown oxide formed by the reaction of iron and oxygen in the catalytic presence of water or air moisture. Rust consists of hydrous iron(III) oxides (Fe2O3·nH2O) and iron(III) oxide-hydroxide (FeO(OH) ...
, use type composition exclusively.
Drawbacks
One common drawback of using composition instead of inheritance is that methods being provided by individual components may have to be implemented in the derived type, even if they are only
forwarding methods (this is true in most programming languages, but not all; see ). In contrast, inheritance does not require all of the base class's methods to be re-implemented within the derived class. Rather, the derived class only needs to implement (override) the methods having different behavior than the base class methods. This can require significantly less programming effort if the base class contains many methods providing default behavior and only a few of them need to be overridden within the derived class.
For example, in the C# code below, the variables and methods of the base class are inherited by the and derived subclasses. Only the method needs to be implemented (specialized) by each derived subclass. The other methods are implemented by the base class itself, and are shared by all of its derived subclasses; they do not need to be re-implemented (overridden) or even mentioned in the subclass definitions.
// Base class
public abstract class Employee
// Derived subclass
public class HourlyEmployee : Employee
// Derived subclass
public class SalariedEmployee : Employee
Avoiding drawbacks
This drawback can be avoided by using
traits
Trait may refer to:
* Phenotypic trait in biology, which involve genes and characteristics of organisms
* Genotypic trait, sometimes but not always presenting as a phenotypic trait
* Personality, traits that predict an individual's behavior.
** ...
,
mixin
In object-oriented programming languages, a mixin (or mix-in) is a class that contains methods for use by other classes without having to be the parent class of those other classes. How those other classes gain access to the mixin's methods depe ...
s, (type)
embedding
In mathematics, an embedding (or imbedding) is one instance of some mathematical structure contained within another instance, such as a group (mathematics), group that is a subgroup.
When some object X is said to be embedded in another object Y ...
, or
protocol
Protocol may refer to:
Sociology and politics
* Protocol (politics)
Protocol originally (in Late Middle English, c. 15th century) meant the minutes or logbook taken at a meeting, upon which an agreement was based. The term now commonly refers to ...
extensions.
Some languages provide specific means to mitigate this:
*
C# provides default interface methods since version 8.0 which allows to define body to interface member.
*
D provides an explicit "alias this" declaration within a type can forward into it every method and member of another contained type.
*
Dart provides mixins with default implementations that can be shared.
*
Go type embedding avoids the need for forwarding methods.
*
Java
Java is one of the Greater Sunda Islands in Indonesia. It is bordered by the Indian Ocean to the south and the Java Sea (a part of Pacific Ocean) to the north. With a population of 156.9 million people (including Madura) in mid 2024, proje ...
provides default interface methods since version 8.
Project Lombok supports delegation using the annotation on the field, instead of copying and maintaining the names and types of all the methods from the delegated field.
*
Julia macros can be used to generate forwarding methods. Several implementations exist such as Lazy.jl and TypedDelegation.jl.
*
Kotlin includes the delegation pattern in the language syntax.
*
PHP
PHP is a general-purpose scripting language geared towards web development. It was originally created by Danish-Canadian programmer Rasmus Lerdorf in 1993 and released in 1995. The PHP reference implementation is now produced by the PHP Group. ...
supports
traits
Trait may refer to:
* Phenotypic trait in biology, which involve genes and characteristics of organisms
* Genotypic trait, sometimes but not always presenting as a phenotypic trait
* Personality, traits that predict an individual's behavior.
** ...
, since PHP 5.4.
*
Raku provides a trait to facilitate method forwarding.
*
Rust
Rust is an iron oxide, a usually reddish-brown oxide formed by the reaction of iron and oxygen in the catalytic presence of water or air moisture. Rust consists of hydrous iron(III) oxides (Fe2O3·nH2O) and iron(III) oxide-hydroxide (FeO(OH) ...
provides traits with default implementations.
*
Scala (since version 3) provides an "export" clause to define aliases for selected members of an object.
*
Swift
Swift or SWIFT most commonly refers to:
* SWIFT, an international organization facilitating transactions between banks
** SWIFT code
* Swift (programming language)
* Swift (bird), a family of birds
It may also refer to:
Organizations
* SWIF ...
extensions can be used to define a default implementation of a protocol on the protocol itself, rather than within an individual type's implementation.
Empirical studies
A 2013 study of 93 open source Java programs (of varying size) found that:
See also
*
Delegation pattern
In software engineering, the delegation pattern is an object-oriented design pattern that allows object composition to achieve the same code reuse as inheritance.
In delegation, an object handles a request by delegating to a second object (the ...
*
Liskov substitution principle
*
Object-oriented design
Object-oriented analysis and design (OOAD) is a technical approach for analyzing and designing an application, system, or business by applying object-oriented programming, as well as using visual modeling throughout the software development proc ...
*
Object composition
In computer science, object composition and object aggregation are closely related ways to combine objects or data types into more complex ones. In conversation, the distinction between composition and aggregation is often ignored. Common ki ...
*
Role-oriented programming
Role-oriented programming as a form of computer programming aims at expressing things in terms that are analogous to human conceptual understanding of the world. This should make programs easier to understand and maintain.
The main idea of role ...
*
State pattern
The state pattern is a Behavioral pattern, behavioral software design pattern that allows an object to alter its behavior when its internal state changes. This pattern is close to the concept of finite-state machines. The state pattern can be inter ...
*
Strategy pattern
In computer programming, the strategy pattern (also known as the policy pattern) is a behavioral software design pattern that enables selecting an algorithm at runtime. Instead of implementing a single algorithm directly, code receives runtime ins ...
References
{{Reflist
Component-based software engineering
Software architecture
Programming principles
Articles with example C Sharp code