Fact-checked by Grok 2 weeks ago

Composition over inheritance

Composition over inheritance is a fundamental design in (OOP) that recommends using —where one class contains instances of other classes as components—rather than class inheritance, where one class derives from another, to achieve , polymorphism, and flexibility in software design. This approach was first prominently articulated by , Richard Helm, Ralph Johnson, and John Vlissides (collectively known as the "Gang of Four") in their 1994 book Design Patterns: Elements of Reusable Object-Oriented Software, where it is stated as a key principle of object-oriented design: "Favor object composition over class inheritance." The principle addresses limitations inherent in inheritance, such as the fragile base class problem, where changes to a superclass can unintentionally break subclasses due to tight coupling and shared implementation details. In contrast, composition promotes by allowing classes to delegate responsibilities to composed objects via interfaces or forwarding methods, enabling easier modification, testing, and extension without altering the containing class's hierarchy. This is exemplified in the wrapper pattern (or ), where a new class wraps an existing one to add or modify behavior while preserving encapsulation and avoiding the need for subclassing. Adopting composition over inheritance enhances software maintainability and adaptability, particularly in large-scale systems, as it avoids inheritance hierarchies that can become rigid and difficult to evolve over time. Influential resources like Joshua Bloch's Effective Java (Item 16) elaborate on its benefits, emphasizing that composition provides a more robust alternative to inheritance for reuse, especially when extending third-party classes or dealing with self-use scenarios where a subclass must invoke its superclass's methods. While inheritance remains useful for modeling true "is-a" relationships (e.g., a Dog is-a Animal), the principle advises reserving it for such cases and defaulting to composition to mitigate risks like the inability to evolve superclasses independently. This guidance has influenced modern OOP languages and frameworks, including , C++, and even non-OOP paradigms like through similar compositional techniques.

Core Concepts

Principle Definition

The principle of composition over inheritance is a fundamental guideline in that recommends favoring —establishing "" relationships where one object contains or delegates to others—over class inheritance, which creates "is-a" relationships by extending superclasses. This preference aims to foster , modularity, and adaptability in by avoiding the rigidity inherent in deep inheritance hierarchies. The principle gained prominence in the 1990s through the influential book Design Patterns: Elements of Reusable Object-Oriented Software (1994) by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides, known as the "Gang of Four," who explicitly advised: "Favor 'object composition' over 'class inheritance'." Building on earlier explorations of reusability, such as Johnson and Foote's 1988 paper "Designing Reusable Classes," which emphasized flexible frameworks using composition for black-box reusability, the Gang of Four positioned it as a core best practice for achieving robust, extensible systems. At its core, the rationale stems from inheritance's tendency to introduce tight and fragility; changes in a base class can propagate unpredictably to subclasses, complicating maintenance in large-scale applications. counters this by enabling , where objects forward requests to composed components, allowing dynamic behavior reconfiguration without hierarchical dependencies. This shift promotes greater flexibility, as systems can assemble functionality from rather than fixed lineages. To visualize the distinction, consider a conceptual UML diagram: an inheritance approach might depict a monolithic tree, with a base Vehicle class branching into specialized subclasses like Car and Truck, each inheriting and potentially overriding shared methods, risking propagation issues. In contrast, a composition diagram shows a Vehicle class containing instances of modular components such as Engine and Wheels, delegating operations like start() to the Engine object, enabling easy swapping of parts without altering the overall structure.

Inheritance Overview

Inheritance is a fundamental mechanism in object-oriented programming (OOP) that enables a , known as a subclass or derived class, to acquire properties, methods, and behaviors from another , referred to as a superclass or base class. This relationship establishes an "is-a" hierarchy, where the subclass is considered a specialized type of the superclass, allowing for the extension or modification of inherited elements. Inheritance manifests in several types, depending on the programming language. Single inheritance occurs when a subclass derives from exactly one superclass, a model supported by languages like and C#, which limits direct inheritance to one base class to avoid complexity. Multilevel inheritance involves a chain of subclasses, where each derives from the previous one, such as class C inheriting from class B, which itself inherits from class A. Hierarchical inheritance features multiple subclasses deriving from a single superclass, promoting shared base functionality across related types. Multiple inheritance, permitted in languages like C++, allows a subclass to derive from more than one superclass simultaneously, enabling the combination of features from unrelated bases but introducing potential ambiguities. Among its strengths, inheritance facilitates by allowing subclasses to inherit and leverage the superclass's implementation without duplication, reducing development effort and promoting consistency. It also supports polymorphism through , where subclasses can provide specialized implementations of inherited methods, enabling flexible and extensible designs that treat subclasses interchangeably with their superclass via a . However, inheritance introduces core drawbacks that can compromise system reliability. The fragile base class problem arises when modifications to a superclass, even seemingly innocuous ones, unintentionally disrupt subclasses that rely on its specific behavior or structure, as developers of the base may not anticipate all extensions. This leads to tight coupling between superclasses and subclasses, where changes propagate unpredictably, increasing maintenance costs. Deep inheritance hierarchies exacerbate these issues, often resulting in the inheritance of unwanted behaviors or dependencies alongside desired functionality—a challenge akin to acquiring an entire when only a specific feature is needed, sometimes termed the "gorilla-banana problem." A illustrative scenario involves a superclass Shape defining common attributes like position and methods such as draw(). Subclasses Circle and Square inherit these, overriding draw() for their geometries. Introducing a new method like rotate() in Shape requires updating all subclasses to handle it appropriately, or risk incomplete functionality and exposing the fragility of the hierarchy.

Composition Overview

Composition is a fundamental principle in object-oriented that involves constructing complex objects by assembling simpler ones through "" relationships, rather than relying on "is-a" hierarchies defined . This approach typically employs aggregation, where one object contains references to others as components, or , where behavior is forwarded to embedded objects. By favoring , designers can create modular systems where parts are independent and interchangeable, promoting flexibility without the rigid dependencies inherent in structures. Object composition manifests in two primary forms: direct embedding, where component objects are instantiated as instance variables within the composing object, establishing a strong ownership relationship; and interface-based delegation, where the composing object holds a reference to another object and forwards method invocations to it, often through a shared interface to maintain abstraction. The delegation pattern exemplifies this, as the delegating class acts as a proxy, routing requests to its components without exposing their internal details, thereby encapsulating behavior dynamically. This pattern, emphasized in seminal design literature, enables runtime substitution of components, enhancing adaptability in evolving systems. The strengths of composition lie in its promotion of between objects, as changes to a component do not propagate to the unless explicitly designed, facilitating easier refactoring and maintenance. Unlike , which can tightly bind subclasses to superclass implementations, composition supports dynamic behavior modifications at by swapping components, reducing fragility and improving overall . For instance, consider a class composed of distinct , Wheels, and Body objects; modifications to the Engine's can occur independently without altering the class itself, allowing for targeted updates and across different vehicle models.

Implementation Approaches

Inheritance-Based Design

Inheritance-based design relies on class hierarchies to promote and polymorphism, where subclasses extend or override behaviors from superclasses. A prominent example is the , a behavioral introduced in the seminal ": Elements of Reusable Object-Oriented Software" by Gamma et al., which uses to define the skeleton of an algorithm in a superclass while permitting subclasses to customize specific steps. In this pattern, the superclass provides a template method that outlines the high-level structure, invoking abstract or concrete primitive operations that subclasses implement or override, ensuring the algorithm's invariant parts remain fixed while allowing variation in details. This approach leverages to achieve algorithmic flexibility without duplicating code across classes. To illustrate inheritance in practice, consider a simple hierarchy modeling animals, a common pedagogical example in object-oriented programming texts. An abstract Animal superclass defines common behaviors like eating, with subclasses such as Dog overriding specific methods like sound production. The following Java pseudocode demonstrates this:
java
abstract class Animal {
    public void eat() {
        System.out.println("This animal eats food.");
    }
    
    public abstract void makeSound();  // Subclasses must implement this
}

class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Woof!");
    }
}

// Usage
Animal myDog = new Dog();
myDog.eat();      // Inherited from Animal
myDog.makeSound(); // Overridden in Dog
This structure allows polymorphic treatment of animals while reusing the eat() method via inheritance. Inheritance-based design proves suitable for stable, shallow hierarchies where relationships are clearly "is-a" and unlikely to evolve dramatically. For instance, in graphical user interface (GUI) frameworks, Java's Abstract Window Toolkit (AWT) employs inheritance to organize components; classes like Panel and Window extend Container, which in turn extends Component, enabling shared functionality for layout and event handling across UI elements. This hierarchy supports consistent behavior in environments where the base structure remains predictable. However, inheritance can lead to pitfalls when hierarchies grow deep or complex, resulting in what is known as "inheritance explosion," where maintenance becomes cumbersome due to tightly coupled classes and increased cognitive load. Consider a library management system where Book inherits from Item, which inherits from Resource; changes to the Resource base class, such as adding metadata fields, propagate unexpectedly to all descendants, complicating updates and debugging. A study found that programs with 0 levels of inheritance required less maintenance effort for understanding tasks than those with 3 or 5 levels, though inheritance depth was not a direct cost factor; the number of relevant methods explained 94% of the variance in task completion time.

Composition-Based Design

Composition-based design assembles object behaviors through "has-a" relationships, where incorporate instances of other to achieve functionality, promoting flexibility over rigid "is-a" hierarchies. The serves as a key example, in which a context maintains a reference to one of several interchangeable strategy objects, each encapsulating a specific or behavior. This allows the context to delegate tasks dynamically at runtime, varying the without altering the context's structure or relying on subclass proliferation. A practical illustration involves modeling behaviors using , as seen in object-oriented simulations where a composes FlyBehavior and QuackBehavior (or equivalent sound behavior) objects. These behaviors can be swapped at to accommodate different , such as a that quacks and swims rather than flies. The following demonstrates this approach:
python
# Behavior interfaces (abstract classes or protocols)
[class](/page/Class) FlyBehavior:
    def fly(self):
        pass

class QuackBehavior:
    def quack(self):
        pass

# Concrete behaviors
class [FlyWithWings](/page/FlyWithWings)([FlyBehavior](/page/FlyBehavior)):
    def fly(self):
        [print](/page/Print)("Flying with wings")

class NoFly([FlyBehavior](/page/FlyBehavior)):  # For swimming ducks
    def fly(self):
        [print](/page/Print)("Cannot fly, swimming instead")

class Quack([QuackBehavior](/page/QuackBehavior)):
    def quack(self):
        [print](/page/Print)("Quack!")

class MuteQuack([QuackBehavior](/page/QuackBehavior)):
    def quack(self):
        [print](/page/Print)("No sound")

# Composed [Bird](/page/Bird) class
class [Bird](/page/Bird):
    def __init__(self, fly_behavior: [FlyBehavior](/page/FlyBehavior), quack_behavior: [QuackBehavior](/page/QuackBehavior)):
        self.fly_behavior = fly_behavior
        self.quack_behavior = quack_behavior

    def perform_fly(self):
        self.fly_behavior.fly()

    def perform_quack(self):
        self.quack_behavior.quack()

    def set_fly_behavior(self, fly_behavior: FlyBehavior):
        self.fly_behavior = fly_behavior

    def set_quack_behavior(self, quack_behavior: QuackBehavior):
        self.quack_behavior = quack_behavior

# Usage example
duck = Bird(FlyWithWings(), Quack())
duck.perform_fly()  # Output: Flying with wings
duck.perform_quack()  # Output: Quack!

# Runtime swap for a swimming duck
duck.set_fly_behavior(NoFly())
duck.perform_fly()  # Output: Cannot fly, swimming instead
This design encapsulates varying behaviors in separate classes, enabling the to adapt without , and aligns with principles favoring for behavioral flexibility. In e-commerce systems, enhances extensibility by allowing an class to incorporate and instances, each handling specific concerns like payment validation or routing. New processors or handlers can be plugged in without modifying the class or creating subclasses for every combination, supporting scalable architectures in dynamic environments. Compared to , composition often reduces the total count by eliminating the need for subclasses to represent behavioral variations; for instance, a requiring 10 subclasses to cover different combinations of s might be refactored to 5 core composed classes plus reusable behavior components, simplifying in large systems.

Interfaces in Composition

Interfaces act as abstract contracts in , specifying a set of methods that classes must implement without dictating how those methods are realized. This allows composing classes to delegate responsibilities to component objects that adhere to the , thereby achieving polymorphism through composition rather than rigid inheritance hierarchies. By defining clear boundaries for , interfaces facilitate the integration of diverse implementations, enabling a higher-level class to treat varied components uniformly while avoiding the tight coupling inherent in subclassing. A practical example in Java illustrates this delegation mechanism. The Drawable interface declares a single method, draw(), which concrete shapes like Circle and Rectangle implement separately.
java
public interface Drawable {
    void draw();
}

public class Circle implements Drawable {
    @Override
    public void draw() {
        // Draw circle logic
    }
}

public class Rectangle implements Drawable {
    @Override
    public void draw() {
        // Draw rectangle logic
    }
}
A composing class, such as Graphics, can then hold a list of Drawable objects and forward calls to them, rendering multiple shapes without inheriting from any specific shape class.
java
import java.util.List;
import java.util.ArrayList;

public class Graphics {
    private List<Drawable> drawables = new ArrayList<>();

    public void addDrawable(Drawable d) {
        drawables.add(d);
    }

    public void render() {
        for (Drawable d : drawables) {
            d.draw();  // Delegation via interface
        }
    }
}
This setup demonstrates how the class achieves polymorphic behavior by composing interchangeable Drawable components, bridging the flexibility of with interface-defined contracts. In practice, this pattern shines in enterprise frameworks where interfaces mitigate issues associated with by permitting a class to adopt behaviors from several sources through . For instance, Spring's relies on interfaces to inject and delegate to composed beans, allowing seamless swapping of implementations (e.g., different data access strategies) without altering the injecting class's structure. This approach supports modular designs that scale effectively, as evidenced in Spring's wiring mechanisms.

Advantages

Flexibility in Design

Composition over inheritance enhances design adaptability by enabling the dynamic assembly of objects through component relationships rather than rigid class hierarchies. This approach allows developers to swap or modify individual components at or compile-time without necessitating the recompilation or restructuring of an entire tree, thereby promoting and reducing the risk of unintended side effects across the system. In contrast to the rigidity of , where changes in a class propagate unpredictably to subclasses, composition isolates modifications to specific parts, facilitating iterative evolution of software designs. A practical illustration of this flexibility appears in game development, where entity-component-system (ECS) architectures leverage composition to build complex entities like characters. For instance, a Character entity can compose modular components such as Weapon and Armor, enabling hot-swapping of these elements—such as equipping a sword or shield—without proliferating subclasses or altering core entity logic. This avoids the explosion of specialized classes (e.g., SwordWarrior or ShieldMage) that inheritance would require, allowing for rapid prototyping and adaptation to new game mechanics. Empirical studies highlight how composition reduces dependency cycles and the effort required for refactoring due to their modular . In real-world applications, this principle underpins architectures, where services are composed as independent, scalable units rather than inherited from monolithic bases, enabling horizontal scaling of specific components without overhauling the entire system.

Enhanced Maintainability

Composition promotes enhanced maintainability in object-oriented designs by enabling localized changes, where modifications to a composed component impact only the classes that directly use it, rather than rippling through an entire hierarchy. This containment reduces the likelihood of unintended side effects and minimizes the effort required to verify and update dependent code during evolution. In contrast, often leads to the fragile base class problem, where alterations to a superclass can unexpectedly break subclasses due to tight across the hierarchy. A practical illustration of this benefit involves updating a DatabaseConnection component within a Service class that composes it; such a change requires adjustments solely in the Service and any classes depending on the Service, without necessitating modifications to unrelated parts of the system. Under an inheritance model, however, a similar update to a superclass like AbstractService would propagate to all subclasses, potentially requiring extensive refactoring across multiple files to maintain correctness. Empirical evidence from controlled experiments supports this distinction, demonstrating that maintenance tasks on programs with deeper inheritance hierarchies (e.g., 5 levels) take longer than on equivalent flat structures (0 levels of inheritance), with performance degrading as depth increases due to heightened cognitive load and coupling. To maximize these maintainability advantages, best practices in composition emphasize creating small, focused classes that adhere to the , thereby isolating potential bugs to narrow scopes and simplifying debugging and testing efforts. This approach not only lowers overall system complexity but also facilitates easier integration with reusable components in larger projects.

Improved Reusability

Composition enables the of components across diverse and unrelated classes without the constraint of sharing a common superclass, thereby promoting greater modularity and adaptability in . This approach contrasts with , where code is limited to hierarchical relationships, often leading to rigid structures that hinder integration into new contexts. In the Jazz toolkit, for instance, small, node types facilitate by allowing visual components to be composed into various locations without dependencies, enhancing overall extensibility. A practical illustration of this reusability is the integration of a Logger utility into multiple applications, such as a and a tool, through rather than inheriting from a base Loggable . With , the Logger object can be instantiated and assigned as a within any , enabling logging functionality to be shared independently of the host class's chain; this avoids the fragility of , where changes to the base could propagate unintended effects across all subclasses. In contrast, an inheritance-based design would require all logging-capable classes to extend the same superclass, limiting reuse to scenarios fitting that and complicating in heterogeneous systems. The exemplifies how composition supports reusable configurations by assembling complex objects from interchangeable parts, allowing the same builder logic to construct varied instances without duplicating code. In this pattern, a orchestrates the builder's step-by-step assembly of components, fostering reuse of the construction process across different product types, such as with varying features. This compositional strategy aligns with the principle of favoring over class inheritance to achieve flexible, reusable object creation, as outlined in foundational literature.

Limitations

Coupling and Fragility

One key limitation of inheritance-based design is the creation of implicit dependencies between base classes and their derivatives, resulting in fragile systems where modifications to the base class can propagate unexpectedly and break subclass functionality. This phenomenon, known as the , occurs because subclasses rely on the internal implementation details of the base class, such as method calls or behavioral assumptions, which may change without altering the base class's public interface. Such fragility is exacerbated by violations of the , which requires that objects of a subclass must be substitutable for objects of the base class without altering the correctness of the program; when inheritance hierarchies fail this, derived classes may exhibit unanticipated behaviors under substitution. A classic illustration involves a base class with methods that invoke each other, where subclasses override one of those methods. For instance, consider a base Storage class with methods store() and retrieve(), where store() internally calls validate(). A subclass FileStorage overrides validate() to add file-specific checks. If the base class is later modified to add a new method archive() that also calls validate(), this seemingly innocuous change can alter the subclass's behavior, causing store() to indirectly invoke the new archiving logic unexpectedly, breaking the intended file-only validation. This tight coupling can be quantified using metrics like , which measures the number of other classes to which a given class is coupled, including those via hierarchies. In inheritance-heavy code, high CBO values signal reduced modularity and increased risk of ripple effects from changes. While generally promotes looser by allowing explicit to independent components, poor implementation—such as excessive reliance on the internal state or methods of delegated objects—can still introduce hidden dependencies, mimicking some fragility risks of inheritance if delegation is not carefully managed.

Performance Overhead

One key limitation of composition over inheritance lies in the overhead introduced by , where calls are forwarded through intermediate objects, adding layers of compared to the direct dispatch in inherited hierarchies. This mechanism, while enabling flexible behavior assembly, incurs additional computational costs for each forwarded invocation, as the must resolve and execute extra lookups and calls. Empirical benchmarks demonstrate that this overhead can manifest as noticeable slowdowns; for instance, a study evaluating across six major Virtual Machines found execution times for delegated operations ranging from 39% to over 100% longer than direct equivalents in certain configurations, particularly on 32-bit systems under Windows. These penalties arise primarily from repeated virtual method dispatches, which JVM profilers like JProfiler or VisualVM reveal as extra invocation cycles in composed designs versus streamlined paths. In performance-critical domains such as systems, including game engines, composing multiple behaviors often requires allocating separate objects for each component, increasing the overall through fragmented usage and garbage collection pressure—contrasting with the consolidated method storage in single-inherited classes. Modern JVMs mitigate some of this through just-in-time () optimizations like method inlining, where frequently delegated calls are replaced with direct code expansion, reducing dispatch overhead in optimized scenarios as observed in the same benchmarks. However, deep or dynamic compositions resist full inlining due to type variability, preserving residual costs. Overall, while slowdowns in shallow compositions are often negligible for general-purpose applications, they can be significant in domains requiring low , where inheritance's efficiency in direct access may outweigh composition's design benefits.

Adoption Challenges

Adopting composition over inheritance can present challenges for developers familiar with inheritance-based paradigms, as it requires a shift in mindset from "is-a" relationships to "has-a" relationships and mastering to achieve polymorphism. This transition can involve more explicit forwarding of calls, which may feel verbose compared to automatic in inheritance. In practice, refactoring legacy codebases with deep inheritance hierarchies can be hindered by the need to redefine interfaces and manage delegations. Additionally, tracing behavior in composed systems may require more effort without specialized tooling.

Empirical Insights

Research Findings

on the principle of composition over has primarily focused on its effects on attributes, including fault proneness, , , , and change propagation. Studies consistently indicate that favoring composition reduces structural complexity associated with deep inheritance hierarchies, leading to improved overall system quality. For instance, controlled experiments and analyses of open-source repositories demonstrate benefits in terms of lower costs and fewer defects. Key metrics analyzed across these studies include (e.g., Lack of Cohesion in Methods, LCOM), (e.g., Coupling Between Objects, ), and . Composition typically yields higher intra-class by encapsulating behaviors in composed objects, while reducing inter-class compared to , where changes in base classes propagate widely. However, these studies have limitations, predominantly focusing on statically typed languages like and C++, with limited empirical data on dynamic languages such as , where runtime polymorphism may alter the trade-offs in and metrics. Recent work, such as a 2024 study on the impact of on code , continues to explore these effects in modern contexts.

Industry Case Studies

In the framework, developed by since its initial release in , the system employs through ViewGroups, which act as containers that aggregate and arrange child objects rather than relying on deep hierarchies. This approach enables developers to build flexible interfaces that adapt to diverse device screens, resolutions, and form factors, mitigating fragmentation across thousands of Android device variants. By composing reusable View components within ViewGroups, such as LinearLayout or RelativeLayout, the framework avoids the rigidity of inheritance-based extensions, allowing modular updates to UI elements without propagating changes across subclass chains. Netflix's adoption of a architecture in the early exemplified by decomposing monolithic applications into independent, composable services that interact via , promoting . This shift enabled parallel development and , improving fault and agility to support growth. Docker's model further illustrates scalability gains via , where services are assembled using Docker Compose files that define multi-container applications without rigid dependencies, promoting extensibility through modular volumes and networks. This facilitates rapid iteration and across cloud infrastructures. Industry experiences highlight that initial refactoring costs for adopting can be substantial but yield long-term returns in through improvements in deployment frequency and change failure rates, as observed in research.

References

  1. [1]
    Effective Java, 3rd Edition [Book] - O'Reilly
    ... Favor composition over inheritanceItem 19: Design and document for ... In this new edition of Effective Java, Bloch explores new design patterns ...
  2. [2]
    Reading 14: Inheritance & Composition - MIT
    Oct 7, 2014 · Favor composition over inheritance from a superclass: the wrapper pattern is an alternative to subclassing that preserves encapsulation and ...<|control11|><|separator|>
  3. [3]
    Design Patterns: Elements of Reusable Object-Oriented Software
    Rating 4.7 20 · 30-day returnsOct 31, 1994 · Description. Copyright 1995; Dimensions: 7-3/8" x 9-1/4"; Pages: 416; Edition: 1st. Book; ISBN-10: 0-201-63361-2; ISBN-13: 978-0-201-63361-0.
  4. [4]
    [PDF] Designing Reuseable Classes - Brian Foote
    Aug 26, 1991 · As with any design task, designing reusable classes requires judgement, ex- perience, and taste. However, this paper has organized many of ...
  5. [5]
  6. [6]
    Objected oriented programming - inheritance - C# - Microsoft Learn
    Feb 16, 2022 · Inheritance in C# enables you to create new classes that reuse, extend, and modify the behavior defined in other classes.
  7. [7]
    Tutorial: Introduction to Inheritance - C# - Microsoft Learn
    C# and . NET support single inheritance only. That is, a class can only inherit from a single class. However, inheritance is transitive, which allows you to ...
  8. [8]
    A study of the fragile base class problem - SpringerLink
    May 25, 2006 · In this paper we study the fragile base class problem. This problem occurs in open object-oriented systems employing code inheritance as an ...Missing: original | Show results with:original
  9. [9]
    Disadvantage of object composition over class inheritance
    Oct 20, 2010 · This article (interview with Erich Gamma, one of the GoF) elaborates clearly why Favor object composition over class inheritance. Share.
  10. [10]
    Composition: The "Has a" Relationship
    This relationship between a Course object and the Student objects that are its data members is called a "has a" relationship.
  11. [11]
    What is Composition Relationship?
    The composition relationship is appropriate to be used in the program if the program has a whole object that must include a part in it. For example, if you ...
  12. [12]
  13. [13]
    Replace Inheritance with Delegation - Refactoring.Guru
    Replacing inheritance with delegation involves creating a superclass object field, delegating methods to it, and making the superclass a helper, not a parent.
  14. [14]
    The Gang of Four :: CC 410 Textbook
    ... Design Patterns: Elements of Reusable Object-Oriented Software by Erich ... Likewise, they favor the use of object composition over inheritance ...
  15. [15]
    Object composition - CSC 207 (Fall 2024) - Samuel A. Rebelsky
    We use the term Composition for a case in which one object/class has a has-a relationship with other objects/classes. Composition seems straightforward enough, ...
  16. [16]
    [PDF] Inheritance and Substitution
    That is, if class Dog is a subclass of class Mammal, and class Mammal is a subclass of class Animal, then Dog will inherit attributes both from Mammal and ...
  17. [17]
    java.awt Class Hierarchy (Java Platform SE 8 ) - Oracle Help Center
    Component (implements java.awt.image.ImageObserver, java.awt.MenuContainer ... For further API reference and developer documentation, see Java SE Documentation.Missing: inheritance | Show results with:inheritance
  18. [18]
    (PDF) A controlled experiment on inheritance depth as a cost factor ...
    Aug 5, 2025 · In two controlled experiments we compare the performance on code maintenance tasks for three equivalent programs with 0, 3, and 5 levels of inheritance.
  19. [19]
    9.2. Software Design and MVC — Masters of Engineering Bridge ...
    Recall that there may be “is a” relationships, also referred to as Generalization/Inheritance ... Aggregate / Composition¶ ... design for the e-Commerce solution ( ...
  20. [20]
    Polymorphism and Interfaces: Chapter 7 of Objects and Java - Artima
    All about polymorphism and interfaces in Java programs ... Talk about the advantages of using interfaces to get polymorphism and composition to get reuse.
  21. [21]
    Dependency Injection :: Spring Framework
    Dependency injection (DI) is a process whereby objects define their dependencies (that is, the other objects with which they work) only through constructor ...Missing: composition | Show results with:composition
  22. [22]
    [PDF] Designing Object-Oriented Frameworks 1 Introduction - ResearchGate
    [20] Johnson, R. and Foote, B. 1988. Designing Reusable Classes. Journal of Object-Oriented Programming. 2(1):22-35.
  23. [23]
    How to preserve the benefits of design patterns - ACM Digital Library
    It is among other things here explained when to use class inheritance as opposed to when to use composition. These kinds of advice are things that should be ...
  24. [24]
    [PDF] Developing games with object composition: A case study using the ...
    This paper shows some of the profits of favoring composition over inheritance, and confirmed through a simplified but practical view how object composition.
  25. [25]
    (PDF) An empirical assessment of refactoring impact on software ...
    Aug 7, 2025 · The aim of this study is to confirm such claims using a hierarchal quality model. We study the effect of software refactoring on software ...
  26. [26]
    [PDF] Assessing the Impact of Microservices Architecture on Software ...
    Abstract: This evaluation delves into the influence of Microservices. Architecture (MSA) on crucial factors like software maintainability and scalability ...
  27. [27]
    Fragile base-class problem, problem? - ACM Digital Library
    Mikhajlov L, Sekerinski E (1998) A study of the fragile base class problem. In: Proceedings of the European Conference on Object-Oriented Programming, pp 355- ...Missing: original | Show results with:original
  28. [28]
    [PDF] A Controlled Experiment on Inheritance Depth as a Cost Factor for ...
    In two controlled experiments we compare the performance on code maintenance tasks for three equivalent programs with 0, 3, and 5 levels of inheritance.
  29. [29]
    Composition vs Inheritance - Thoughtbot
    Nov 7, 2016 · Prefer composition over inheritance. What advantages does composition have over inheritance? Sign up to receive a weekly recap from ...Composition Vs Inheritance · Coupling And Cohesion · Using Inheritance<|control11|><|separator|>
  30. [30]
    Builder - Refactoring.Guru
    This example of the Builder pattern illustrates how you can reuse the same object construction code when building different types of products, such as cars ...Builder in Java · Builder in TypeScript · Builder in Python · Builder in Go
  31. [31]
    (PDF) Fragile base-class problem, problem? - ResearchGate
    Aug 6, 2025 · The fragile base-class problem (FBCP) has been described in the literature as a consequence of “misusing” inheritance and composition in object-oriented ...
  32. [32]
    Delegation Pattern in Java: Mastering Efficient Task Assignment
    Delegation is a design pattern where an object passes on a task to a helper object. In object-oriented programming, delegation refers to evaluating a member ( ...
  33. [33]
    [PDF] On Performance of Delegation in Java
    Oct 25, 2009 · This paper presents empirical data about performance penalties, introduced due to delegation. Six of the most com- mon Java Virtual Machines ( ...Missing: overhead benchmarks
  34. [34]
    Optimizing an HTML5 game engine using composition over ...
    Mar 10, 2014 · It turns out that inheritance in JavaScript will inherently lead to polymorphism and huge object sizes and therefore to performance issues.
  35. [35]
    Inheritance versus Delegation: which is more energy efficient?
    Sep 25, 2020 · In this paper, we present the results of preliminary experiments that explore the Replace Inheritance with Delegation refactoring, and its ...
  36. [36]
    Java inheritance vs. composition: How to choose | InfoWorld
    Compare inheritance and composition, the two fundamental ways to relate Java classes, then practice debugging ClassCastExceptions in Java inheritance.<|control11|><|separator|>
  37. [37]
    (PDF) Experimental Validation of Inheritance Metrics' Impact on ...
    Software faults can cause trivial annoyance to catastrophic failures. Recent work in software fault prediction (SFP) advocates the need for predicting faults ...
  38. [38]
    [PDF] Inheritance Usage Pa erns in Open-Source Systems - Strathprints
    Metrics associated with inheritance focus on Depth of. Inheritance Tree (DIT) and Number of Children (NOC) associated with hierarchy members ...
  39. [39]
    [PDF] Inheritance software metrics on smart contracts - arXiv
    Jul 16, 2020 · We present a small empirical study that captures inheritance- metric ... A controlled experiment on inheritance depth as a cost factor for code ...
  40. [40]
    Rebuilding Netflix Video Processing Pipeline with Microservices
    Jan 10, 2024 · This architecture shift greatly reduced the processing latency and increased system resiliency. Moving away from the use of dedicated instances ...
  41. [41]
    [PDF] 2022 Accelerate State of DevOps Report - Dora.dev
    Our research focuses on examining how capabilities and practices predict the outcomes that we consider central to DevOps: • Software delivery performance – The ...