link: Object Oriented Programming

Relations Between Objects

Overview

In software development, understanding the various types of relationships between objects is crucial for designing robust and maintainable systems. Beyond Inheritance and interface implementation, several other relationships define how objects interact and depend on each other within a system.

Abstract

This note explores the foundational relationships such as dependency, association, aggregation, and composition, each playing a unique role in object-oriented design and affecting how classes and objects are interconnected.

Content

Key Concepts

The relationships between objects in object-oriented programming are essential for defining how objects and classes interact. These relationships can be organized into several categories, each signifying different ways classes and objects can be associated:

Important

  • Dependency: A change in one class affects another.
  • Association: A general connection between classes where one class knows about and interacts with another.
  • Aggregation: A specialized form of association where one class is made up of one or more instances of other classes.
  • Composition: A stricter form of aggregation where the contained class’s lifecycle is controlled by the container class.
  • Realization: This relationship occurs when a class implements an interface, thereby adhering to the contract the interface provides.
  • Generalization: A relationship where a more specialized element (a derived class) inherits from a more general element (a base class). This is a form of inheritance.

Dependency

Dependency relationships

Content

Dependency is the most basic and the weakest type of relations between classes. In object-oriented programming (OOP), a dependency exists whenever one class uses another. This can be through direct instantiation, method calls, or through passing instances as parameters. Dependencies make one class reliant on another, often leading to a higher risk of bugs when changes are made:

Example

Here’s a practical C# example illustrating a basic dependency relationship:

csharp

using System;
 
public class Car
{
   public void Start() => Console.WriteLine("Car started");
   public void Stop() => Console.WriteLine("Car stopped");
}
 
public class Driver
{
   public void Drive(Car car)
   {
       car.Start();
       Console.WriteLine("Car is being driven by the driver");
       car.Stop();
   }
}
 
class Program
{
   static void Main()
   {
       Car myCar = new Car();      // Creating a Car object
       Driver john = new Driver(); // Creating a Driver object
 
       john.Drive(myCar);  // Demonstrating dependency
   }
}
 

In this code:

  • The Driver class has a dependency on the Car class because it uses the Car object to perform its functions. The method Drive directly interacts with Car, implying that any change in Car’s interface would require changes in Driver.

Example

This C# code snippet demonstrates a clear dependency where Driver relies on Car. Such dependencies are vital to identify as they dictate the robustness and flexibility of your code structure.

Link to original

Association

Association relationships

Content

Association in object-oriented design signifies a broader and more permanent relationship compared to simple dependencies:

Important

Association often represents links like fields in a class that refer to other objects. These links enable one object to use or interact with another object continuously, unlike a simple dependency which might only represent temporary use.

Example

Here’s a practical example to illustrate association and its contrast with dependency:

csharp

class Professor
{
   public Student Student { get; set; }
 
   public void Teach(Course c)
   {
       this.Student.remember(c.GetKnowledge());
   }
}
 

In this C# example, the Professor class has a property Student which exemplifies an association because it represents a permanent link to a Student object that any method of the Professor can use.

Meanwhile, the Teach method’s use of the Course object to call GetKnowledge shows a Dependency relationships. Changes in Course’s method could disrupt the Professor’s functionality, highlighting how dependencies are based on method use.

The presence of both association and dependency in this example helps delineate the nuances between these two types of relationships.

Link to original

Aggregation

Aggregation relationships

Content

Aggregation allows one object to contain a group of objects but without exclusive ownership, meaning the contained objects can exist independently of the container, which is different from composition where the lifecycle of contained objects is managed by the container.

Important

Aggregation is used to represent relationships where the “part” (component) can exist separately from the “whole” (aggregate). This relationship is particularly useful in models where components need to be shared or reused across different parts of a system

Example

Here is a practical example to illustrate the concept of aggregation in C#:

using System;
using System.Collections.Generic;
 
public class Employee
{
    public int EmployeeId { get; set; }
    public string Name { get; set; }
 
    public Employee(int employeeId, string name)
    {
        EmployeeId = employeeId;
        Name = name;
    }
 
    public void DisplayEmployeeDetails()
    {
        Console.WriteLine($"Employee ID: {EmployeeId}, Name: {Name}");
    }
}
 
public class Department
{
    public string DepartmentName { get; set; }
    public List<Employee> Employees { get; set; }
 
    public Department(string departmentName)
    {
        DepartmentName = departmentName;
        Employees = new List<Employee>();
    }
 
    public void AddEmployee(Employee employee)
    {
        Employees.Add(employee);
    }
 
    public void DisplayDepartmentDetails()
    {
        Console.WriteLine($"Department: {DepartmentName}");
        foreach (var employee in Employees)
        {
            employee.DisplayEmployeeDetails();
        }
    }
}
 
class Program
{
    static void Main()
    {
        Employee emp1 = new Employee(1, "John Doe");
        Employee emp2 = new Employee(2, "Jane Smith");
 
        Department department = new Department("Engineering");
        department.AddEmployee(emp1);
        department.AddEmployee(emp2);
 
        department.DisplayDepartmentDetails();
    }
}
 

In this C# example:

  • The Department class aggregates Employee objects, representing a relationship where the department (whole) consists of employees (parts).
  • The Employee objects can exist independently of the Department, indicating an aggregation, not composition.
Link to original

Composition

Composition relationships

Content

Composition is a stringent form of aggregation in object-oriented programming that defines a “part-whole” relationship where parts cannot exist independently of the whole. This type of relationship is crucial for ensuring that objects are well-integrated within a system, enforcing encapsulation and enhancing the system’s robustness.

Composition is a specific kind of aggregation known for its strictness in part-whole relationships:

Important

Composition ensures that when the container (whole) is destroyed, its contents (parts) are also destroyed. This relationship is ideal for representing natural part-whole hierarchies in an application, such as graphical user interfaces or management systems where components must not exist without the whole.

Example

using System;
 
public class Engine
{
    public void Start() => Console.WriteLine("Engine started");
    public void Stop() => Console.WriteLine("Engine stopped");
}
 
public class Car
{
    private Engine engine = new Engine(); // Composition: Car "has-a" Engine
 
    public void Start()
    {
        engine.Start();
        Console.WriteLine("Car started");
    }
 
    public void Stop()
    {
        engine.Stop();
        Console.WriteLine("Car stopped");
    }
}
 
class Program
{
    static void Main()
    {
        Car myCar = new Car();
        myCar.Start();
        myCar.Stop();
    }
}
 

In this C# example:

  • The Car class is composed of an Engine. The Car owns the Engine and controls its lifecycle.
  • The Engine cannot exist independently of the Car, demonstrating a composition relationship.
  • The methods Start and Stop in Car delegate to Engine, encapsulating its functionality within the Car.
Link to original

Summary

Cheat Sheet

Exploring how all these relationships interconnect provides insights into their practical applications and differences:

  • Dependency: Suggests a unidirectional relationship where changes in one class (Class B) could affect another class (Class A).
  • Association: Indicates a bidirectional relationship where each class knows about and can interact with the other.
  • Aggregation: Implies a whole/part relationship without life dependency. Class A contains Class B, but B can exist independently of A.
  • Composition: Represents a stronger whole/part relationship where the life of Class B is dependent on the life of Class A.
  • Implementation and Inheritance: Both deal with how classes share interfaces and implementations, but inheritance implies a direct lineage.

References

Design Patterns