Sunday, October 11, 2026
HomeC ProgrammingSorts and Examples in C++, Java, Python

Sorts and Examples in C++, Java, Python


Write a category that counts what number of tags are added to a set by extending an current tag set, add three tags, and it studies six. The identical subclass offers the identical unsuitable reply in C++, Java and Python, as a result of the bottom class’s add_all occurs to name add, and the subclass counted each. Inheritance is essentially the most direct technique to reuse code in object-oriented programming, and that instance is the clearest image of what it prices: a subclass depends upon how its dad or mum is written, not solely on what it guarantees.

This information explains inheritance as an object-oriented idea, with the identical instance written in C++, Java and Python: what it’s and why it exists, the 5 sorts of inheritance and which languages assist them, overriding and calling the dad or mum’s model, the delicate base class drawback, and when composition is the higher alternative. Each program was run for this text on Ubuntu 24.04 with GCC 13.3 and Clang 18.1.3 (-std=c++17 -Wall -Wextra -pedantic -Werror), OpenJDK 21 (javac -Xlint:all -Werror) and Python 3.13 (-W error), and the three variations of every instance print equivalent output, captured verbatim. The code is in a GitHub repository whose construct repeats these checks on every commit. For the C++ particulars (entry management, constructors, digital destructors) see inheritance in C++.

The Brief Reply

What’s inheritance in OOP? A technique to outline a brand new class from an current one. The brand new class (the subclass) will get the prevailing class’s information and strategies, can add its personal, and might change strategies it inherited. A subclass object can be utilized wherever the dad or mum kind is anticipated.

What are the sorts of inheritance? Single, multilevel, hierarchical, a number of and hybrid. C++ and Python assist all 5 with courses. Java permits one dad or mum class, so a number of and hybrid inheritance are doable solely by interfaces.

Is inheritance unhealthy? No, nevertheless it {couples} a subclass to its dad or mum’s implementation. Use it when the subclass really is a form of the dad or mum and will likely be used by the dad or mum’s kind; for reusing code alone, composition is normally safer.

What Is Inheritance?

Inheritance in object-oriented programming is a relationship between courses through which a subclass (derived or youngster class) acquires the attributes and strategies of a superclass (base or dad or mum class). The subclass can add members and override inherited strategies, and an object of the subclass can be utilized wherever an object of the superclass is anticipated. It expresses an “is-a” relationship: an e mail notification is a notification.

Every language makes use of its personal vocabulary for a similar concept:

Idea C++ Java Python
The present class Base class Superclass Base class, dad or mum class
The brand new class Derived class Subclass Subclass, derived class
Declaring it class E mail : public Notification class E mail extends Notification class E mail(Notification):
Calling the dad or mum’s technique Notification::format(m) tremendous.format(m) tremendous().format(m)
Marking an override override (checked by the compiler) @Override (checked by the compiler) No key phrase; @typing.override is checked by kind checkers solely
Root of each class None java.lang.Object object

Inheritance is among the 4 concepts normally listed because the pillars of object-oriented programming, with encapsulation, abstraction and polymorphism. It’s the mechanism that makes one type of polymorphism doable: code written towards the dad or mum kind works with each subclass, as proven in polymorphism in C++, Java and Python.

One Instance in Three Languages

A notification system has one technique to ship a message and several other methods to format it. The bottom class owns the shared habits (ship), and every subclass modifications one step (format).

C++:

// notifications.cpp - inheritance in C++: a base class with shared habits,
// two derived courses that override one step of it.
#embody <iostream>
#embody <reminiscence>
#embody <string>
#embody <utility>
#embody <vector>

class Notification {
public:
    specific Notification(std::string recipient) : recipient_(std::transfer(recipient)) {}
    digital ~Notification() = default;

    // Shared by each form of notification.
    void ship(const std::string& message) const {
        std::cout << "to " << recipient_ << ": " << format(message) << 'n';
    }

protected:
    // The step every sort can change.
    digital std::string format(const std::string& message) const { return message; }

non-public:
    std::string recipient_;
};

class E mail : public Notification {
public:
    utilizing Notification::Notification;
protected:
    std::string format(const std::string& message) const override {
        return "[email] " + Notification::format(message);    // prolong the dad or mum's model
    }
};

class Sms : public Notification {
public:
    utilizing Notification::Notification;
protected:
    std::string format(const std::string& message) const override {
        return "[sms] " + message.substr(0, 19);               // change it
    }
};

int important() {
    std::vector<std::unique_ptr<Notification>> outbox;
    outbox.push_back(std::make_unique<Notification>("ops-team"));
    outbox.push_back(std::make_unique<E mail>("<!--email_off-->[email protected]<!--/email_off-->"));
    outbox.push_back(std::make_unique<Sms>("+1-555-0100"));

    for (const auto& n : outbox)
        n->ship("Disk utilization on db-01 is above 90 %");
}

Java:

// Notifications.java - inheritance in Java: the identical three courses.
import java.util.Listing;

public class Notifications {
    static class Notification {
        non-public last String recipient;

        Notification(String recipient) { this.recipient = recipient; }

        last void ship(String message) {
            System.out.println("to " + recipient + ": " + format(message));
        }

        protected String format(String message) { return message; }
    }

    static class E mail extends Notification {
        E mail(String recipient) { tremendous(recipient); }

        @Override
        protected String format(String message) {
            return "[email] " + tremendous.format(message);
        }
    }

    static class Sms extends Notification {
        Sms(String recipient) { tremendous(recipient); }

        @Override
        protected String format(String message) {
            return "[sms] " + message.substring(0, Math.min(19, message.size()));
        }
    }

    public static void important(String[] args) {
        Listing<Notification> outbox = Listing.of(
            new Notification("ops-team"),
            new E mail("<!--email_off-->[email protected]<!--/email_off-->"),
            new Sms("+1-555-0100"));

        for (Notification n : outbox)
            n.ship("Disk utilization on db-01 is above 90 %");
    }
}

Python:

"""notifications.py - inheritance in Python: the identical three courses."""


class Notification:
    def __init__(self, recipient):
        self._recipient = recipient

    def ship(self, message):
        print(f"to {self._recipient}: {self.format(message)}")

    def format(self, message):
        return message


class E mail(Notification):
    def format(self, message):
        return "[email] " + tremendous().format(message)


class Sms(Notification):
    def format(self, message):
        return "[sms] " + message[:19]


if __name__ == "__main__":
    outbox = [Notification("ops-team"), Email("<!--email_off-->[email protected]<!--/email_off-->"), Sms("+1-555-0100")]
    for n in outbox:
        n.ship("Disk utilization on db-01 is above 90 %")

Output (equivalent for all three):

to ops-team: Disk utilization on db-01 is above 90 %
to <!--email_off-->[email protected]<!--/email_off-->: [email] Disk utilization on db-01 is above 90 %
to +1-555-0100: [sms] Disk utilization on db-01

The three packages make the identical design selections in numerous syntax:

  • ship is inherited unchanged. Not one of the subclasses defines it. The loop calls ship on every object, and ship calls format, which runs the subclass’s model: [email] and [sms] seem with out the loop understanding which type it holds. In Java, ship is said last so no subclass can change the shared half.
  • E mail extends the dad or mum’s habits. It calls the dad or mum’s format (Notification::format, tremendous.format, tremendous().format) and provides a prefix. That’s the regular manner so as to add to an inherited technique fairly than change it.
  • Sms replaces it. It by no means calls the dad or mum and truncates the message to 19 characters as an alternative.
  • The recipient stays non-public. Every subclass units it by the dad or mum’s constructor and by no means touches it immediately. In C++ the constructor is inherited with utilizing Notification::Notification;; Java wants an specific tremendous(recipient); Python inherits __init__ like another technique.

One distinction issues greater than the syntax. Java (besides last, static and non-public strategies) and Python strategies could be overridden by default, whereas in C++ solely capabilities declared digital could be; with out digital (and with override eliminated, since it might not compile), the C++ loop would print three plain messages.

Varieties of Inheritance

The 5 sorts of inheritance Arrows level from the derived class to its base. Shaded containers are root courses. Single C++ sure Java sure Python sure A B Multilevel C++ sure Java sure Python sure A B C Hierarchical C++ sure Java sure Python sure A B C D A number of C++ sure Java interfaces solely Python sure A B C Hybrid (right here, a diamond) C++ sure Java interfaces solely Python sure A B C D Java permits one base class; a category can implement any variety of interfaces.
5 shapes a category hierarchy can take. C++ and Python permit all of them with extraordinary courses. Java permits one dad or mum class, so its a number of and hybrid hierarchies are constructed from interfaces.

The 5 varieties are names for the shapes a category hierarchy can take:

  1. Single inheritance: one subclass, one dad or mum. E mail derives from Notification.
  2. Multilevel inheritance: a series. C derives from B, which derives from A; C inherits from each.
  3. Hierarchical inheritance: a number of subclasses of 1 dad or mum. E mail and Sms are each notifications.
  4. A number of inheritance: one class with a number of dad and mom. Supported for courses in C++ and Python; Java permits it just for interfaces. Coated in depth in a number of inheritance in C++.
  5. Hybrid inheritance: any mixture of the above. The frequent case is the diamond, the place two dad and mom share a grandparent.

Python can present the way it resolves every form. Each class has a technique decision order (MRO): the sequence of courses searched when a technique is seemed up.

"""types_of_inheritance.py - single, multilevel, hierarchical and a number of
inheritance, and the strategy decision order Python makes use of for every."""


class Gadget: go                      # base
class Scanner(Gadget): go             # single
class Printer(Gadget): go             # hierarchical: two courses from one base
class Copier(Scanner, Printer): go    # a number of (and a diamond by Gadget)
class ColorCopier(Copier): go         # multilevel: Gadget -> Scanner -> Copier -> ColorCopier

for cls in (Scanner, Copier, ColorCopier):
    print(f"{cls.__name__:12} MRO: " + " -> ".be part of(c.__name__ for c in cls.__mro__))
print("Copier is a Gadget:", issubclass(Copier, Gadget))

Output:

Scanner      MRO: Scanner -> Gadget -> object
Copier       MRO: Copier -> Scanner -> Printer -> Gadget -> object
ColorCopier  MRO: ColorCopier -> Copier -> Scanner -> Printer -> Gadget -> object
Copier is a Gadget: True

Copier inherits from each Scanner and Printer, and Gadget seems as soon as in its MRO, after each of them. Python all the time merges a shared ancestor into one, utilizing an algorithm known as C3 linearization. C++ makes the alternative default alternative: a shared base seems twice except it’s declared digital, which is why the diamond drawback is a C++ subject greater than a Python one.

The Fragile Base Class Drawback

Inheritance lets a subclass name the dad or mum’s strategies, nevertheless it additionally lets the dad or mum name the subclass’s overrides. That second course is the place most inheritance bugs come from. This tag set counts each try so as to add a tag:

"""fragile_base.py - the identical dependency on a base class's implementation."""


class Tags:
    def __init__(self):
        self._tags = set()

    def add(self, tag):
        self._tags.add(tag)

    def add_all(self, tags):
        for t in tags:
            self.add(t)

    def dimension(self):
        return len(self._tags)


class CountingTags(Tags):
    def __init__(self):
        tremendous().__init__()
        self.makes an attempt = 0

    def add(self, tag):
        self.makes an attempt += 1
        tremendous().add(tag)

    def add_all(self, tags):
        self.makes an attempt += len(tags)
        tremendous().add_all(tags)


if __name__ == "__main__":
    t = CountingTags()
    t.add_all(["urgent", "billing", "eu"])
    print(f"tags saved: {t.dimension()}, makes an attempt counted: {t.makes an attempt}")

Output:

tags saved: 3, makes an attempt counted: 6

Three tags had been added, three had been saved, and 6 had been counted. CountingTags.add_all added 3 after which known as Tags.add_all, which calls self.add for every tag, and self.add is the subclass’s override, which added 1 three extra instances. The Java and C++ variations within the repository (FragileBase.java, fragile_base.cpp) are the identical program and printed the identical line. C++-specific traps that compile cleanly are collected in inheritance in C++.

Nothing in Tags‘s public interface says that add_all calls add. It’s an implementation element, and the subclass’s correctness depends upon it. If a later model of Tags rewrote add_all to insert tags immediately, this subclass would begin counting appropriately with none change of its personal. And if the subclass had been mounted by dropping its add_all override and counting on add being known as, that very same change to Tags would break it the opposite manner: three tags, zero counted. That is the fragile base class drawback: modifications inside a dad or mum class which might be invisible to its callers can nonetheless break its subclasses.

Inheritance vs Composition

The identical counter constructed by composition holds a Tags object as an alternative of inheriting from one:

"""composition.py - the counting set once more, constructed by composition: it holds a
Tags object as an alternative of inheriting from it, so add_all can not name again into it."""
from fragile_base import Tags


class CountingTags:
    def __init__(self):
        self._tags = Tags()
        self.makes an attempt = 0

    def add(self, tag):
        self.makes an attempt += 1
        self._tags.add(tag)

    def add_all(self, tags):
        self.makes an attempt += len(tags)
        self._tags.add_all(tags)

    def dimension(self):
        return self._tags.dimension()


if __name__ == "__main__":
    t = CountingTags()
    t.add_all(["urgent", "billing", "eu"])
    print(f"tags saved: {t.dimension()}, makes an attempt counted: {t.makes an attempt}")

Output:

tags saved: 3, makes an attempt counted: 3

Tags.add_all nonetheless calls self.add, however self is now the interior Tags object, not the counter, so the counter’s add just isn’t known as again. The rely is appropriate, and it might keep appropriate no matter Tags does internally. The price is that the counter should ahead each technique it desires to reveal (dimension right here), and it’s not usable as a Tags.

Query Inheritance Composition
Relationship is-a: an E mail is a Notification has-a: a counter has a tag set
Usable wherever the dad or mum kind is anticipated Sure No, except it implements the identical interface
Is determined by the opposite class’s internals Sure, by overridden strategies the dad or mum calls No, solely on its public strategies
Effort Inherits the whole lot mechanically Forwards every technique explicitly
Matches A household of varieties used by one interface Reusing habits inside a category

The rule normally quoted from Design Patterns (Gamma, Helm, Johnson and Vlissides, 1994) is “favor object composition over class inheritance”. It doesn’t imply “by no means inherit”: the notification instance is an efficient use, as a result of callers work with Notification and each subclass honors what format means.

When to Use Inheritance

Inheritance suits when all of those maintain:

  1. The subclass is a form of the dad or mum, and code will use it by the dad or mum’s kind.
  2. It retains the dad or mum’s guarantees. Anyplace a Notification works, an E mail should work too. That is the Liskov substitution precept.
  3. The dad or mum was designed to be prolonged: it paperwork which strategies subclasses could override and what the dad or mum calls internally, or it’s an summary class or interface with no implementation to rely on.

If any of those fails, compose as an alternative. A sensible signal is a subclass that overrides strategies solely to disable them, or that exists solely to reuse two or three of the dad or mum’s strategies.

Key Takeaways

  • Inheritance defines a brand new class from an current one: the subclass will get the dad or mum’s members, can add its personal, and might override strategies.
  • The identical design reads the identical in C++, Java and Python; the variations are the key phrase, how the dad or mum known as, and that C++ strategies have to be digital to be overridden.
  • There are 5 varieties: single, multilevel, hierarchical, a number of and hybrid. Java helps the final two solely by interfaces.
  • Python merges a shared ancestor as soon as, by its technique decision order; C++ duplicates it except inherited digital.
  • A subclass depends upon its dad or mum’s implementation. A counter that prolonged a tag set reported 6 for 3 tags in all three languages.
  • Composition avoids that dependency: the identical counter holding a tag set reported 3.

Incessantly Requested Questions

Conclusion

Inheritance offers a category two issues directly: the dad or mum’s code and the dad or mum’s kind. The notification instance wants each, which is why it reads cleanly in all three languages. The tag counter wished solely the code, and paid for the sort it didn’t want by relying on particulars it couldn’t see. Asking which of the 2 a design actually wants is many of the resolution between inheriting and composing.

For the C++ specifics, see the guides to inheritance in C++ and a number of inheritance. Extra object-oriented programming subjects are collected within the OOP part.

Supply Code and Checks

inheritance-concepts

All packages on this web page are within the oop/inheritance-concepts listing of the MYCPLUS C++ examples repository.

Construct and check:

bash checks/run_tests.sh g++

What the construct checks. On Linux, with GCC and with Clang, it compiles the C++ packages with -Wall -Wextra -pedantic -Werror, compiles the Java packages with javac -Xlint:all -Werror on Java 21, runs the Python packages with -W error on Python 3.12, and checks that each model of every instance prints precisely the output proven on this web page.

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments