Fact-checked by Grok 2 weeks ago

Class hierarchy

In , a class hierarchy is a taxonomic structure that organizes es into a tree-like arrangement, where derived es (subclasses) inherit attributes, methods, and behaviors from parent es (superclasses), enabling efficient classification and extension of object types. This hierarchy typically supports single , meaning each has at most one direct superclass, forming a , where each has at most one direct superclass, with a single inheritance path from any to the root that serves as the foundation for all others. At the apex of most class hierarchies is a universal root class, such as Progress.Lang.Object in OpenEdge ABL or Object in languages like Java and Python, which provides fundamental functionality like object instantiation and basic methods without inheriting from any other class. Subclasses extend this base by adding specialized features, overriding inherited methods for customization, or introducing new ones, which promotes code reuse and reduces redundancy across related classes. For instance, a base class like Person might define common attributes such as name and age, which a subclass like Student inherits and augments with enrollment-specific methods. Class hierarchies facilitate key principles of object-oriented design, including polymorphism, where objects of different subclasses can be treated uniformly through references to their superclass, allowing dynamic invocation based on the actual object type. They also support , with superclasses often declared as to enforce that implementations occur only in subclasses, ensuring a clear progression from general to specific functionality. During object creation, constructors are invoked sequentially from the root class upward to the instantiated subclass, guaranteeing proper initialization across the hierarchy. This structure is fundamental in languages like , , and C++, aiding in the development of scalable, maintainable software systems.

Fundamentals

Definition

In object-oriented programming, a class hierarchy is a tree-like structure organizing classes such that child classes inherit properties, methods, and behaviors from parent classes, facilitating and . This arrangement forms a family of related classes, where the relationships are defined by inheritance, allowing for specialization and extension while maintaining shared attributes across levels. Key terminology includes the superclass (also known as the base class or parent class), which serves as the origin of inherited elements, providing common data and functionality to its descendants. The subclass (or derived class or child class) extends the superclass by inheriting its features and potentially adding or overriding them to create more specific implementations. The inheritance relationship itself is the directed link from subclass to superclass, enabling this hierarchical flow of attributes and behaviors. The concept of class hierarchy originated in the 1960s with the development of the programming languages by and at the Norwegian Computing Center. I (1962–1964) and 67 (1967) introduced classes and through a mechanism called class prefixing, where a new class could prefix an existing one to form a subclass, allowing the modeling of real-world hierarchies in for discrete event systems. This innovation enabled programmers to represent complex, interrelated entities, such as objects in a simulation, by grouping common properties in superclasses and specializing them in subclasses.

Key Components

A class hierarchy in is structured around distinct levels that organize classes from general to specific. The root class, often serving as the ultimate superclass with no parent, provides foundational attributes and behaviors shared across the entire hierarchy, such as in Java's Object class which defines common methods like toString() and equals(). classes occupy the middle layers, extending the root or other intermediates to add specialized features while inheriting from above, facilitating progressive refinement. classes, positioned at the bottom with no subclasses of their own, represent the most concrete implementations tailored for specific uses and cannot be further extended in the hierarchy. The primary relationship defining a class hierarchy is the "is-a" relationship, established through , where a subclass is considered a specialized instance of its superclass, enabling and specialization. This manifests as direct inheritance, where a immediately extends one superclass, or indirect inheritance, where a inherits from a superclass through one or more intermediate levels in the chain. Class hierarchies vary in depth and breadth, influencing their complexity and reusability. Depth refers to the maximum number of levels from the root to a leaf class, measured as the Depth of Inheritance Tree (DIT); single-level hierarchies involve only direct inheritance from the root, while multi-level ones span multiple tiers for greater specialization. Breadth is captured by metrics like the Number of Children (NOC), indicating the average or maximum immediate subclasses per class; flat hierarchies emphasize width with many direct subclasses for broad categorization, whereas deep hierarchies prioritize height for layered reuse, though excessive depth can complicate maintenance. In practice, depth is often preferred over excessive breadth to enhance method reuse via inheritance.

Implementation in Programming

Inheritance Mechanisms

Inheritance mechanisms in class hierarchies facilitate the extension and reuse of code by allowing subclasses to derive properties and behaviors from superclasses, establishing an "is-a" relationship where the subclass is a specialized form of the superclass. Single inheritance is a fundamental mechanism where a subclass inherits from exactly one superclass, promoting a tree-like hierarchy that simplifies structure and avoids certain ambiguities. In this model, the subclass gains access to the superclass's fields and methods, enabling —where the subclass provides a specific implementation of an inherited —and controlled field access based on visibility rules. This approach ensures clear lineage and supports straightforward , as seen in early object-oriented languages like . Multiple inheritance extends this by permitting a subclass to derive from more than one superclass, allowing the combination of features from disparate classes to form more complex behaviors. However, it introduces challenges such as the diamond problem, which occurs when a subclass inherits from two classes that share a common superclass, potentially leading to duplicate instances of the common ancestor and ambiguities in resolution or access. To resolve this, techniques like in C++ ensure that the common superclass is inherited only once, creating a shared instance across paths and eliminating duplication. In languages like C++ that support different inheritance access specifiers, these refine by determining how the base class's members are accessed in the derived class and externally, balancing encapsulation with extensibility. Public exposes the superclass's public members to the subclass and external code, maintaining their accessibility and modeling an "is-a" relationship. Protected inheritance maps the superclass's public and protected members to protected in the subclass, allowing subclass access while hiding them from external code and supporting internal extensions. Private inheritance maps the superclass's public and protected members to private in the subclass, while private members remain inaccessible to the subclass, emphasizing implementation hiding and without exposing the . These specifiers collectively ensure that hierarchies respect data privacy while enabling targeted .

Language-Specific Features

In , class hierarchies support single for es, where a subclass can extend only one superclass using the extends keyword, thereby inheriting its fields, methods, and nested classes. This design ensures a clear, linear chain of , with all es ultimately deriving from the Object class as the . To achieve multiple inheritance-like behavior, allows a to implement multiple interfaces via the implements keyword, enabling the of abstract methods and constants from several sources without the ambiguities associated with multiple . C++ permits , allowing a derived to inherit directly from more than one base , which provides greater flexibility in combining behaviors but introduces potential complexities such as name ambiguities and duplicate subobjects in diamond-shaped hierarchies. To mitigate these issues, particularly the creation of multiple instances of a common base , C++ uses with the virtual keyword in the base class specifier (e.g., class Derived : virtual public Base {}), ensuring a single shared subobject for the virtual base across the hierarchy. This approach resolves ambiguities by enforcing a unique instance and follows a specific construction order: virtual bases are initialized first in depth-first, left-to-right sequence, followed by non-virtual bases. Python supports multiple inheritance natively, where a class can specify multiple superclasses in its definition, and the method resolution order (MRO) determines the sequence for attribute and method lookups during execution. The MRO is computed using the C3 linearization algorithm, which produces a consistent, deterministic ordering that respects the while preserving monotonicity (ensuring superclasses appear before subclasses in the order) and local precedence (maintaining the order of direct superclasses as listed). The algorithm linearizes a C with direct superclasses B1, ..., BN via the formula L[C] = C + merge(L[B1], ..., L[BN], B1, ..., BN), where the merge operation iteratively selects the first class from the heads of the input linearizations that does not appear in the tails of any preceding list, appending it to the result and removing it from all lists; this process repeats until all classes are incorporated or a arises, in which case an exception is raised.

Examples and Applications

Real-World Code Examples

Class hierarchies are commonly illustrated through everyday entities to demonstrate in . A foundational example involves modeling , where a base class captures shared behaviors, and subclasses specialize them. This approach promotes by allowing subclasses to inherit and extend functionality from the superclass. Consider a simple animal hierarchy in . The base Animal class includes a universal eat() method, while subclasses like Mammal and Bird override a move() method to reflect species-specific actions.
class Animal {
    method eat() {
        print "Eating food";
    }
    method move() {
        // Generic movement
        print "Moving around";
    }
}

class Mammal extends Animal {
    method move() {
        super.eat();  // Calls parent's eat method
        print "Walking on land";
    }
}

class Bird extends Animal {
    method move() {
        super.eat();  // Calls parent's eat method
        print "Flying in the sky";
    }
}
In this structure, both Mammal and Bird inherit the eat() method directly from Animal, but override move() for tailored behavior. The super keyword enables traversal up the hierarchy to invoke the superclass's eat() method, ensuring shared logic is preserved without duplication. This pattern is widely used in introductory OOP resources to highlight single inheritance. Another practical illustration is a vehicle hierarchy, which models transportation systems with varying attributes and operations. The Vehicle superclass defines common properties like speed and color, while subclasses such as Car and Motorcycle add specific features like passenger capacity or helmet requirements.
abstract class Vehicle {
    attribute speed: integer;
    attribute color: string;
    method accelerate(increment: integer) {
        speed += increment;
    }
    method getSpeed() {
        return speed;
    }
}

class Car extends Vehicle {
    attribute passengers: integer = 4;
    method honk() {
        print "Beep beep!";
    }
}

class Motorcycle extends Vehicle {
    attribute helmetRequired: boolean = true;
    method revEngine() {
        print "Vroom!";
    }
}
Here, Car and Motorcycle inherit acceleration capabilities from Vehicle but introduce unique methods and attributes suited to their types. This hierarchy supports polymorphic treatment, where vehicles can be handled uniformly via the base class while leveraging subclass specifics. Such designs appear in educational examples for simulating real-world systems like fleet management. The use of super in hierarchy traversal, as shown earlier, is essential for constructor chaining and method overriding across levels. For instance, in a deeper hierarchy, a subclass constructor might call super() to initialize parent attributes before adding its own, maintaining the integrity of inherited state. This mechanism is a core feature in languages supporting OOP, facilitating modular extensions without redundant code.

Design Patterns Using Hierarchies

Class hierarchies serve as a foundational structure in object-oriented , enabling polymorphism and extensibility by allowing subclasses to specialize behavior while inheriting common functionality from superclasses. This approach promotes and maintainability, as abstract base classes define interfaces and algorithms that subclasses implement or override. In particular, hierarchies facilitate patterns where , algorithmic skeletons, or event notification mechanisms are delegated to subclasses, reducing tight and enhancing flexibility. The exemplifies the use of hierarchies to define algorithmic frameworks. In this , an abstract superclass provides a template method that outlines the skeleton of an , calling primitive operations, their concrete classes, and post-processing steps. Subclasses inherit this structure and override the primitive operations to customize specific steps without altering the overall flow, ensuring the parts remain fixed while allowing variation in implementation details. This pattern is particularly effective in frameworks where a common process, such as or game loops, requires at certain points. For instance, a base for application frameworks might define initialization, execution, and cleanup phases, with subclasses providing domain-specific logic for each. The Factory Method pattern leverages class hierarchies for object creation in a creational context. Here, an abstract creator declares a factory method that returns an abstract product, deferring the of concrete products to subclasses of the creator. This hierarchy of creator classes allows each subclass to decide which specific product instance to create, promoting the open-closed principle by enabling new product types without modifying existing code. Commonly applied in scenarios like creation in applications or UI component factories, the pattern isolates logic, making systems more extensible—for example, a base Application with subclasses for different types, each overriding the factory method to produce corresponding documents. An adaptation of the incorporates class hierarchies to handle event notification through specialized subjects and observers. In the standard behavioral Observer pattern, a subject maintains a list of observers and notifies them of state changes, but hierarchies extend this by subclassing the subject for different event types or the observer for varied response behaviors. A base class defines attachment, detachment, and notification methods, while subclasses implement specific update logic; similarly, an class allows concrete observer subclasses to handle notifications differently based on context. This hierarchical approach is useful in event-driven systems like GUI frameworks, where a hierarchy of components (subjects) notifies specialized listener subclasses (observers) for actions such as button clicks or menu selections, the notifier from the response logic.

Benefits and Limitations

Advantages

Class hierarchies in provide significant benefits by enabling structured code organization and leveraging to enhance . One primary advantage is , where subclasses inherit methods and attributes from superclasses, thereby reducing duplication and allowing developers to build upon existing functionality without rewriting code. This mechanism not only accelerates development but also minimizes errors by relying on tested components. For instance, in a hierarchy modeling shapes, a base class can define common operations like area calculation, which subclasses directly. Another key benefit is improved , as modifications to a superclass automatically propagate to all subclasses, streamlining updates across the . This reduces the scope of changes required during refactoring or bug fixes, making large codebases more manageable and less prone to inconsistencies. in base classes further supports this by localizing implementation details, so alterations in data structures or algorithms affect only dependent subclasses without rippling through the entire system. Additionally, class hierarchies excel at modeling complexity by mirroring real-world taxonomies and relationships, which enhances code readability and conceptual clarity. By organizing classes into logical parent-child structures, developers can represent hierarchical domains—such as biological classifications or organizational charts—more intuitively, facilitating easier comprehension and extension of the system. This approach promotes a natural of entities and their interactions, aiding in both and analysis phases of .

Challenges and Drawbacks

One significant challenge in class hierarchies is tight coupling, where subclasses become highly dependent on the internal implementation details of their superclasses, leading to fragility when the superclass is modified. This phenomenon, known as the fragile base class problem, arises because changes to a superclass—such as adding or altering a method—can unexpectedly break subclasses that override or rely on those methods, requiring widespread recompilation and testing across the . Studies of open-source systems have shown that while this coupling does not always increase fault proneness directly, it complicates by intertwining the evolution of base and derived classes. Multiple inheritance exacerbates coupling issues through the diamond problem, an ambiguity that occurs when a subclass inherits from two classes that share a common superclass, resulting in duplicate instances of the shared superclass and unclear resolution of methods or fields. For instance, if class D inherits from classes B and C, both of which inherit from A, then D may contain two conflicting copies of A's members, leading to runtime errors or unpredictable behavior during invocation. This problem demands complex resolution mechanisms, such as in C++, but even these can introduce overhead and semantic inconsistencies in object initialization. Overuse of inheritance often results in deep hierarchies, where classes form long chains of specialization, increasing overall system complexity and hindering and efforts. Deep trees, typically exceeding three to five levels, make it difficult to trace behavior across the , as changes propagate unpredictably and refactoring becomes risky due to the interconnected dependencies. Guidelines recommend such structures to keep them within short-term cognitive limits, as deeper hierarchies correlate with higher costs and reduced comprehensibility in object-oriented systems.

Composition vs Inheritance

In object-oriented programming, composition establishes a "has-a" relationship between classes by having one class contain instances of other classes as fields, rather than deriving from them through . This approach allows the containing class to delegate to its components, promoting greater flexibility and by enabling the assembly of objects at without rigid hierarchical ties. Unlike , which enforces an "is-a" relationship and can lead to tightly coupled code, composition supports , making it easier to swap or extend components without affecting the overall structure. The principle of favoring was articulated in the seminal book Design Patterns: Elements of Reusable Object-Oriented Software by , Richard Helm, Ralph Johnson, and John Vlissides (1994), often referred to as the (GoF). The authors recommend this strategy because can increase complexity and fragility in large systems, as changes to a base class propagate unpredictably to subclasses, whereas keeps classes more encapsulated and focused on single responsibilities. is particularly advantageous when seeking runtime polymorphism, as it allows dynamic selection and delegation to component objects, avoiding the static binding inherent in hierarchies. A classic example illustrates this distinction: consider modeling a vehicle system where a class could extend a base class via , inheriting methods like accelerate() but risking unwanted behaviors from Vehicle (e.g., if Vehicle includes boat-specific logic). In contrast, using , the Car class would hold references to separate , , and objects, delegating calls like startEngine() to the Engine instance; this enables easy replacement of parts (e.g., swapping an electric Engine for a gasoline one) without altering the Car's core structure, enhancing and adaptability.

Interfaces and Abstract Classes

Abstract classes provide a mechanism for partial implementation within class hierarchies, allowing developers to define common structure and behavior while deferring specific details to subclasses. They include concrete methods that supply shared functionality and abstract methods that declare signatures without implementation, requiring subclasses to provide concrete realizations to fulfill the hierarchy's contract. This enforces a consistent interface across related classes, promoting code reuse and polymorphism without allowing instantiation of the abstract class itself. In the context of object-oriented programming, abstract classes serve as foundational elements in type hierarchies, where subtypes must adhere to the supertype's behavioral specifications to enable substitution—ensuring that objects of a subclass can replace those of the superclass without altering program correctness. For instance, an abstract Shape class might define a concrete method for drawing and abstract methods for calculating area and perimeter, compelling subclasses like Circle and Rectangle to implement the latter while inheriting the former. This approach supports incremental design and library organization by encapsulating shared abstractions at higher levels of the hierarchy. Interfaces, in contrast, represent pure contracts in hierarchies, specifying a set of signatures without any , thereby focusing solely on what behaviors a must support rather than how they are realized. This design enables a form of of behavior, as a single can implement multiple interfaces, combining disparate capabilities without the risks associated with , such as conflicts. Interfaces thus extend hierarchies by allowing orthogonal behaviors to be mixed into , enhancing flexibility in modeling complex relationships. The integration of abstract classes and interfaces in hierarchies combines the strengths of partial implementation with pure contractual obligations, often using abstract classes as bases that implement one or more interfaces to enforce multifaceted contracts. For example, an abstract base class for geometric shapes might implement an interface for drawable objects, providing shared drawing logic while leaving shape-specific computations abstract, and subclasses then fulfill both the interface's requirements and the base class's partial implementation. This pattern, sometimes involving interface mixins, allows hierarchies to balance enforcement of common behaviors with extensibility, as seen in designs where abstract classes declare pure virtual functions to integrate ordering constraints across multiple inheritance paths.

References

  1. [1]
    Class Hierarchies
    Apr 21, 1997 · In general, each class inherits variables and methods from its superclass, and may add more variables and methods or override existing ones.
  2. [2]
    Class hierarchies and inheritance - Progress Documentation
    Mar 18, 2024 · The root class of a hierarchy is the class that does not inherit from any other class. In ABL, the root class of all classes is the built-in, ...
  3. [3]
    Class hierarchies - Python Programming MOOC 2025
    A class can inherit the traits of another class. In addition to these inherited traits a class can also contain traits which are unique to it. Knowing this, it ...
  4. [4]
    Inheritance and class hierarchies
    A family of classes is known as a class hierarchy. As in a biological family, there are parent classes and child classes. Child classes can inherit data and ...
  5. [5]
    [PDF] The Birth of Object Orientation: the Simula Languages - UiO
    In 1962 Kristen Nygaard, KN, initiated a project for the development of a discrete event simulation language, to be called Simula. At the time KN.
  6. [6]
    OOP: Class Hierarchy - Homepages of UvA/FNWI staff
    3.1 OOP: Class Hierarchy. In object-oriented programming, a class is a template that defines the state and behavior common to objects of a certain kind.
  7. [7]
    Limit Inheritance Hierarchy Depth (OOP03) - learn.adacore.com
    A class inheritance hierarchy consists of a set of types related by inheritance. Each class, other than the root class, is a subclass of other classes, and each ...Missing: breadth flat
  8. [8]
    [PDF] Class Hierarchies and Inheritance
    Most of the time, any “is a” relationship between objects should certainly result in the creation of a subclass. Object-oriented code usually involves a lot of ...<|control11|><|separator|>
  9. [9]
    Inheritance
    An indirect base class is inherited from two or more levels up the class hierarchy. In the case of single inheritance, a class is derived from one base class.
  10. [10]
    [PDF] Towards a metrics suite for object oriented design - DSpace@MIT
    Generally it is better to have depth than breadth in the class hierarchy, since it promotes reuse of methods through inheritance. It is not good practice ...<|control11|><|separator|>
  11. [11]
    Single versus multiple inheritance in object oriented programming
    As Booth defines, "Inheritance is a relationship among classes, wherein one class shares the structure and behavior defined in one (single inheritance) or more.
  12. [12]
    Multiple and Virtual Inheritance, C++ FAQ - Standard C++
    It solves a problem shared by both bridge and nested generalization, namely it allows a user to pass any gas powered vehicle using a common base class. Finally ...
  13. [13]
    [PDF] CZ: Multiple Inheritance Without Diamonds
    The diamond problem arises when a class C inherits an ancestor. A through more than one path. This is particularly problematic when A has fields—should C ...
  14. [14]
    [PDF] Object-Oriented Programming: Inheritance - User pages
    With inheritance, the common instance variables and methods of all the classes in the hierarchy are declared in a superclass. When changes are required for ...
  15. [15]
    Inheritance - Learning the Java Language
    In the Java language, classes can be derived from other classes, thereby inheriting fields and methods from those classes.
  16. [16]
  17. [17]
    Multiple Base Classes | Microsoft Learn
    Oct 3, 2025 · In a multiple-inheritance model (where classes are derived from more than one base class), the base classes are specified using the base-list grammar element.
  18. [18]
    The Python 2.3 Method Resolution Order
    Abstract: This document is intended for Python programmers who want to understand the C3 Method Resolution Order used in Python 2.3.
  19. [19]
    Inheritance in Java - GeeksforGeeks
    Oct 14, 2025 · Java IS-A type of Relationship. IS-A represents an inheritance relationship in Java, meaning this object is a type of that object. Java. Loading ...
  20. [20]
    Java super Keyword (With Examples) - Programiz
    In this tutorial, we will learn about the super keyword in Java with the help of examples. The Java super keyword is used in subclasses to access superclass ...
  21. [21]
    Java Inheritance Programming - Vehicle class hierarchy - w3resource
    May 16, 2025 · Write a Java program to create a vehicle class hierarchy. The base class should be Vehicle, with subclasses Truck, Car and Motorcycle.Missing: OOP | Show results with:OOP
  22. [22]
    Vehicle hierarchy - CS@Columbia
    Pseudo-Java code illustrating "vehicle" object hierarchy abstract class Vehicle { private Color color; protected int speed; public Color getColor() { return ...Missing: pseudocode | Show results with:pseudocode
  23. [23]
    Design Patterns: Elements of Reusable Object-Oriented Software
    Rating 4.7 20 · 30-day returnsOct 31, 1994 · Design Patterns: Elements of Reusable Object-Oriented Software. By Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides; Published Oct 31, ...
  24. [24]
    Observer Design Pattern - SourceMaking
    Model the dependent functionality with an "observer" hierarchy. The Subject is coupled only to the Observer base class. The client configures the number and ...Discussion · Example · Rules Of Thumb
  25. [25]
    (PDF) The object oriented model and its advantages - ResearchGate
    Aug 10, 2025 · This paper examines some advantages of the Object Oriented Model (OOM), such as reuse of code, better structured programs and easier transition from analysis ...
  26. [26]
    (PDF) Object-Oriented Development and Inheritance - ResearchGate
    Apr 27, 2024 · Object-oriented programming encapsulate data objects and the operations on the objects into classes. A user program can only access the ...
  27. [27]
    [PDF] An Overview of Object-Oriented Programming (Oop) And Its Impact ...
    This review provides a reference point to clearly distinguish the existing advantages and disadvantages of OOP. This source contains research papers and ...
  28. [28]
    (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 ...
  29. [29]
    CZ: multiple inheritance without diamonds - ACM Digital Library
    Oct 19, 2008 · Instead, we address the diamond problem directly, considering two difficulties it causes: ... Read More · CZ: multiple inheritance without ...
  30. [30]
    Barriers to Refactoring - Communications of the ACM
    Oct 1, 2017 · DIT, which captures a characteristic of the inheritance hierarchy, is the length of the longest path from a class to a root of the hierarchy. In ...
  31. [31]
    Some Pitfalls of Inheritance - CODE Magazine
    Inheritance hierarchies should be as flat as possible*,* because deep class hierarchies are more difficult to work with and to maintain than flat ones. A rule ...
  32. [32]
    Composition vs Inheritance - Thoughtbot
    Nov 7, 2016 · This is the opening line of the classic manual on software design Design Patterns: Elements of Reusable Object-Oriented Software, published in ...
  33. [33]
    [PDF] Software Composition with Multiple Nested Inheritance - Cornell ...
    This paper introduces multiple nested inheritance and shows that it is an effective lan- guage mechanism for extending and composing large bodies of software.
  34. [34]
    [PDF] Abstract Classes and Interfaces - University of Maryland
    They are an ideal mechanism when you want to create something for objects that are closely related in a hierachy. Implementation. • An abstract class is a class ...
  35. [35]
    [PDF] Data Abstraction and Hierarchy - Department of Computer Science
    Data abstraction is a valuable method for organizing programs to make them easier to modify and maintain. Inheritance allows one implementation of a data ...
  36. [36]
    [PDF] Object-oriented Programming - II Interfaces
    Multiple interface inheritance hierarchy between interfaces and classes: a class implements interfaces. • There is only one single implementation inheritance ...
  37. [37]
    [PDF] Chapter 16: Abstract Classes and Multiple Inheritance
    An abstract class lets us define and enforce a common interface, or behavior, for a set of related classes. Class derivation, combined with methods defined ...