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 Type | Description | Use Case |
|---|---|---|
| Single | One subclass, one superclass | Basic extension |
| Multiple | One subclass, multiple superclasses | Behavior combination |
| Multilevel | Inheritance chain across levels | Deep specialization |
| Hierarchical | One superclass, multiple subclasses | Common base class |
| Hybrid | Combination of types | Complex 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 problemInheritance 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.
| Aspect | Inheritance | Composition |
|---|---|---|
| Relationship | is-a | has-a |
| Coupling | Tight | Loose |
| Flexibility | Static | Dynamic |
| Use cases | Specialization | Behavior 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'sDesign 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 openedMethod 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 circleMultiple 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.