Definition and Overview

Concept

Inheritance: mechanism for creating new classes from existing ones. Enables hierarchical classification. Derived classes inherit attributes and behaviors from base classes.

Purpose

Purpose: promote code reuse, establish is-a relationships, enable polymorphism. Supports abstraction and modularity.

Core elements

Core elements: superclass (parent/base class), subclass (child/derived class). Subclass inherits fields and methods, optionally extends or modifies them.

Relation to OOP

Relation: one of four main OOP pillars alongside encapsulation, polymorphism, and abstraction. Foundation for object hierarchies.

Key terminology

Key terms: class hierarchy, method overriding, code reuse, subtype, specialization.

"Inheritance is the mechanism of basing an object or class upon another object or class, retaining similar implementation." -- Grady Booch

Types of Inheritance

Single Inheritance

Single inheritance: subclass inherits from one superclass. Simplest form. Example: Dog inherits from Animal.

Multiple Inheritance

Multiple inheritance: subclass inherits from multiple superclasses. Enables combining behaviors but may cause ambiguity (diamond problem).

Multilevel Inheritance

Multilevel inheritance: chain of inheritance across multiple levels. Example: Animal → Mammal → Dog.

Hierarchical Inheritance

Hierarchical inheritance: one superclass, multiple subclasses. Example: Animal → Dog, Cat, Bird.

Hybrid Inheritance

Hybrid inheritance: combination of two or more inheritance types. Often complex, requires careful design.

Inheritance TypeDescriptionUse Case
SingleOne subclass, one superclassBasic extension
MultipleOne subclass, multiple superclassesBehavior combination
MultilevelInheritance chain across levelsDeep specialization
HierarchicalOne superclass, multiple subclassesCommon base class
HybridCombination of typesComplex hierarchies

Syntax and Implementation

General syntax

Syntax varies by language. Typically: class Subclass extends Superclass or similar.

Example in Java

class Animal { void eat() { System.out.println("Eating..."); }}class Dog extends Animal { void bark() { System.out.println("Barking..."); }}

Example in C++

class Animal {public: void eat() { std::cout << "Eating..." << std::endl; }};class Dog : public Animal {public: void bark() { std::cout << "Barking..." << std::endl; }};

Access control

Inheritance respects access modifiers: private members not inherited directly, protected and public accessible depending on inheritance type.

Constructor behavior

Superclass constructor invoked before subclass constructor. Ensures base initialization.

Advantages

Code reuse

Reuse: avoid redundancy by inheriting common functionality.

Extensibility

Extensible: add new features by subclassing without modifying existing code.

Polymorphism support

Supports polymorphism: enables dynamic method dispatch.

Logical hierarchy

Organizes classes logically via is-a relationships.

Maintenance ease

Simplifies maintenance: updates in superclass propagate to subclasses.

Disadvantages and Limitations

Tight coupling

Tight coupling: subclasses tightly bound to superclasses, reducing flexibility.

Fragile base class problem

Changes in base class may unexpectedly affect subclasses.

Multiple inheritance complexity

Multiple inheritance can cause ambiguity and complexity (diamond problem).

Overuse risks

Overusing inheritance leads to deep hierarchies, hard to understand and maintain.

Inheritance vs behavior

Inheritance models is-a relationships, not always suitable for code reuse (favor composition).

Method Overriding

Definition

Method overriding: subclass provides own implementation of superclass method.

Purpose

Purpose: customize or extend superclass behavior.

Rules

Rules: method signature must match, access level cannot be more restrictive, return type compatible.

Dynamic dispatch

Dynamic dispatch resolves overridden method calls at runtime based on object type.

Example

class Animal { void sound() { System.out.println("Generic sound"); }}class Dog extends Animal { @Override void sound() { System.out.println("Bark"); }}

Use of super and this Keywords

super keyword

super: references superclass members. Used to invoke superclass methods or constructors.

this keyword

this: references current object members. Used to distinguish instance variables from parameters.

Calling superclass constructor

super() used to call superclass constructor explicitly inside subclass constructor.

Accessing overridden methods

super.methodName() invokes superclass version despite overriding.

Example

class Animal { void sound() { System.out.println("Animal sound"); }}class Dog extends Animal { void sound() { super.sound(); System.out.println("Dog barks"); }}

Multiple Inheritance

Definition

Multiple inheritance: subclass inherits from more than one superclass.

Languages supporting

C++ supports directly. Java uses interfaces to simulate multiple inheritance.

Diamond problem

Diamond problem: ambiguity when superclasses share common base. Resolved differently per language.

Resolution strategies

Strategies: virtual inheritance in C++, interfaces and default methods in Java.

Example in C++

class A {public: void display() { std::cout << "A" << std::endl; }};class B : public A {};class C : public A {};class D : public B, public C {}; // Diamond problem

Inheritance vs Composition

Definition of composition

Composition: class contains objects of other classes, models has-a relationships.

Differences

Inheritance: is-a relationship, static at compile time. Composition: has-a relationship, flexible.

Advantages of composition

Better encapsulation, reduces coupling, easier to change behavior at runtime.

When to use inheritance

Use inheritance when subclass truly is a specialized type of superclass.

When to use composition

Use composition for code reuse without strict is-a semantics.

AspectInheritanceComposition
Relationshipis-ahas-a
CouplingTightLoose
FlexibilityStaticDynamic
Use casesSpecializationBehavior reuse

Inheritance and Polymorphism

Definition of polymorphism

Polymorphism: ability of objects to be treated as instances of their superclass while exhibiting different behaviors.

Subtype polymorphism

Subtype polymorphism: subclass objects substituted for superclass references.

Method overriding and dynamic dispatch

Method overriding enables polymorphism. Dynamic dispatch resolves method calls at runtime.

Benefits

Benefits: flexible code, extensibility, runtime behavior customization.

Example

Animal a = new Dog();a.sound(); // Calls Dog's implementation, not Animal's

Design Principles and Best Practices

Favor composition over inheritance

Composition preferred to reduce coupling and increase flexibility.

Use inheritance for is-a relationships

Only subclass when there is a true subtype relationship.

Keep inheritance hierarchies shallow

Deep hierarchies complicate understanding and maintenance.

Prefer interfaces/abstract classes

Use interfaces or abstract classes to define contracts, enable multiple inheritance of types.

Override methods carefully

Override only when behavior truly changes; call superclass methods if needed.

Code Examples

Single Inheritance Example (Java)

class Vehicle { void start() { System.out.println("Vehicle started"); }}class Car extends Vehicle { void openSunroof() { System.out.println("Sunroof opened"); }}Car myCar = new Car();myCar.start(); // Vehicle startedmyCar.openSunroof(); // Sunroof opened

Method Overriding Example (Java)

class Shape { void draw() { System.out.println("Drawing shape"); }}class Circle extends Shape { @Override void draw() { System.out.println("Drawing circle"); }}Shape s = new Circle();s.draw(); // Drawing circle

Multiple Inheritance Simulation (Java Interfaces)

interface Printable { void print();}interface Showable { void show();}class Document implements Printable, Showable { public void print() { System.out.println("Printing document"); } public void show() { System.out.println("Showing document"); }}

Use of super Keyword

class Parent { void msg() { System.out.println("Parent message"); }}class Child extends Parent { void msg() { super.msg(); System.out.println("Child message"); }}

References

  • Booch, G., Object-Oriented Analysis and Design with Applications, Benjamin/Cummings, Vol. 2, 1994, pp. 123-145.
  • Gamma, E., Helm, R., Johnson, R., Vlissides, J., Design Patterns: Elements of Reusable Object-Oriented Software, Addison-Wesley, 1994, pp. 45-78.
  • Schildt, H., Java: The Complete Reference, McGraw-Hill, 11th ed., 2018, pp. 234-267.
  • Lippman, S.B., Lajoie, J., Moo, B.E., C++ Primer, Addison-Wesley, 5th ed., 2012, pp. 350-390.
  • Martin, R.C., Clean Code: A Handbook of Agile Software Craftsmanship, Prentice Hall, 2008, pp. 90-115.