Welcome to the world of Object-Oriented Programming (OOP)! If you’ve successfully grasped the concepts of Classes and Objects, then you’re ready for the next big step: understanding how these classes interact.

Think of classes as blueprints for different components of a massive machine. This chapter is about drawing the wires and bolts that connect these components together, allowing them to work as a unified system. Mastering these relationships is essential for writing efficient, flexible, and powerful code!


1. Understanding Class Relationships: Why Connect Them?

In real-world systems, no entity exists completely in isolation. A bank account needs a customer; a car needs an engine; a team needs players.

Object-Oriented Programming (OOP) allows us to model these real-world connections using formal relationships between classes. The two main types of relationships you must know are Inheritance and Association.

Quick Tip: Understanding these relationships helps you design systems that are easier to debug and update (this links back to the concept of maintainability in software development).


2. Inheritance: The "Is-A" Relationship

What is Inheritance?

Inheritance is a fundamental relationship where one class is based on another class, taking on its properties and methods. It models an "Is-A" relationship.

Example: A 'Dog' is a 'Mammal'. A 'Car' is a 'Vehicle'.

  • The original class is called the Base Class (or Parent Class, or Superclass).
  • The new, specialised class is called the Subclass (or Derived Class, or Child Class).

The primary advantage? Code Reuse! If all animals can eat, you define the eat() method once in the Base Class (Animal), and all Subclasses (Dog, Cat, Bird) automatically inherit it.

Analogy: The Vehicle Blueprint

Imagine you have a detailed blueprint for a generic Vehicle (Base Class). This blueprint includes methods like start_engine() and properties like colour and speed.

When you create a blueprint for a Car (Subclass), you don't rewrite everything. You just say: "A Car inherits from Vehicle," and then you add the specific things only a car has, like number_of_doors.

Protected Access Modifier (The Middle Ground)

When defining properties or methods in the Base Class, we use access modifiers (like public or private) to control visibility (this is part of encapsulation).

The Protected access modifier (symbolised by # in diagrams) is special in inheritance:

  • Public (+): Accessible by everyone.
  • Private (-): Accessible only within the defining class.
  • Protected (#): Accessible within the defining Base Class AND by all Subclasses, but NOT by outside objects.

Why use Protected? It allows subclasses to manage or modify core features of the parent class, while still shielding those features from random manipulation by other parts of the program.

Overriding Methods

Sometimes, a Subclass inherits a method, but the way it performs that action needs to be different from the Base Class. This is where Overriding comes in.

Overriding is when a method defined in the Base Class is redefined (changed) in the Subclass, so the subclass instance behaves differently.

Step-by-step Example of Overriding:

  1. The Vehicle (Base Class) has a method: calculate_fuel_economy().
  2. The ElectricCar (Subclass) inherits this method.
  3. Since an Electric Car doesn't use petrol, the subclass overrides calculate_fuel_economy() to calculate energy consumption (e.g., kilowatt-hours per km) instead.
  4. When you call this method on an ElectricCar object, the subclass's version is used.
Key Takeaway: Inheritance

Inheritance models 'Is-A'. It involves a Base Class and a Subclass, and it enables specialisation and code reuse. Overriding allows subclasses to change inherited behaviour. The Protected (#) modifier grants access only to the Base Class and its Subclasses.


3. Association: The "Has-A" Relationship

What is Association?

Association is a broader, weaker relationship between two objects where one object merely uses or contains another object. It models a "Has-A" relationship.

If Object A uses Object B, we say Object A is associated with Object B.

Did you know? Association is a much weaker relationship than inheritance. An object can exist perfectly well without the object it is associated with.

Example: Football Simulation (as per the syllabus context)

  • We have a Team class and a Player class.
  • Does a Team "Is-A" Player? No.
  • Does a Team "Has-A" Player? Yes, a Team object contains or makes use of multiple Player objects.

We use association whenever objects need to interact or link together, but one is not a specialized version of the other.

Key Takeaway: Association

Association models 'Has-A'. It means one object makes use of another. It’s used when objects are separate entities that need to collaborate (e.g., a Customer has an Address).


4. Visualising Relationships: Class Diagrams

To clearly communicate how classes are linked, programmers use diagrams (often based on UML – Unified Modeling Language). You need to be familiar with the notation for inheritance and association, and how access levels are marked.

Access Specifier Symbols

These symbols indicate the visibility of properties and methods within the class box:

  • +: Public Access (Anyone can access)
  • -: Private Access (Only the class itself can access)
  • #: Protected Access (Accessible by the class and its Subclasses)
Example Class Structure (in a Diagram)

Class Name

- private_attribute
# protected_attribute
+ public_attribute

- private_method()
+ public_method()

Inheritance Notation (Specialisation)

Inheritance is shown by a solid line with an **unfilled, closed arrowhead** pointing from the Subclass to the Base Class.

The arrow points to the parent: "The Subclass depends on the Parent's definition."

Subclass                              Base Class

|

Association Notation (Usage)

Association is shown by a solid line connecting the two associated classes. You might see an arrow indicating the direction of use, or no arrow if the relationship goes both ways.

Team Class ------------------ Player Class

If the relationship is one-directional (e.g., Class A uses Class B, but B doesn't know about A), you would add a simple open arrowhead.

Class A ------------------> Class B

Quick Review: Relationship Symbols
  • Inheritance: Unfilled triangular arrow pointing UP (to the parent).
  • Association: Simple solid line or line with an open arrow.
  • Access: + (Public), - (Private), # (Protected).

Keep practising identifying these symbols in diagrams and relating them back to the core OOP concepts of specialisation (Inheritance) and collaboration (Association). You've got this!