Aggregation is a concept in object-oriented programming that defines a “has-a” relationship between objects, where one class contains an object reference to another class.
Unlike inheritance (an “is-a” relationship), aggregation models relationships where one object is part of another but can exist independently.
In C#, aggregation is often implemented by including instances of one class as fields in another class.
This tutorial will cover:
1. Basics of Aggregation
In aggregation, one class holds a reference to another class, creating a “whole-part” relationship. For example, a Library might contain multiple Book objects, but each Book can exist independently of the Library. Aggregation allows you to combine different objects while maintaining their independence.
2. Implementing Aggregation in C#
In C#, aggregation is implemented by defining a class that includes another class as a field or property. This allows the containing class (the “whole”) to interact with instances of the other class (the “part”) without owning or controlling their lifecycle.
Example: Library and Book Relationship
using System; using System.Collections.Generic; public class Book { public string Title { get; set; } public string Author { get; set; } public Book(string title, string author) { Title = title; Author = author; } public void DisplayInfo() { Console.WriteLine($"Title: {Title}, Author: {Author}"); } } public class Library { public string Name { get; set; } public List<Book> Books { get; set; } = new List<Book>(); // Aggregates books public Library(string name) { Name = name; } public void AddBook(Book book) { Books.Add(book); } public void DisplayBooks() { Console.WriteLine($"Books in {Name}:"); foreach (Book book in Books) { book.DisplayInfo(); } } } public class AggregationExample { public static void Main() { Library library = new Library("City Library"); // Creating books independently of the library Book book1 = new Book("1984", "George Orwell"); Book book2 = new Book("To Kill a Mockingbird", "Harper Lee"); // Adding books to the library library.AddBook(book1); library.AddBook(book2); library.DisplayBooks(); } }
Explanation:
- The Library class aggregates a list of Book objects.
- Books are created independently of the Library and then added to it.
- Each Book can exist independently of the Library, illustrating an aggregation relationship.
Output:
Books in City Library: Title: 1984, Author: George Orwell Title: To Kill a Mockingbird, Author: Harper Lee
3. Aggregation vs Composition
While both aggregation and composition represent “has-a” relationships, they differ in terms of ownership and lifecycle:
- Aggregation: The contained object can exist independently of the container. For example, a Library has Books, but Books can exist outside a Library.
- Composition: The contained object is strongly associated with the container, often created and destroyed along with it. For example, a Car has Engine, and if the Car is destroyed, the Engine typically is as well.
Example: Car and Engine (Composition) vs. Library and Book (Aggregation)
using System; public class Engine { public int HorsePower { get; set; } public Engine(int horsepower) { HorsePower = horsepower; } public void Start() { Console.WriteLine($"Engine with {HorsePower} HP started."); } } public class Car { public string Model { get; set; } public Engine CarEngine { get; set; } // Composition relationship public Car(string model, int horsepower) { Model = model; CarEngine = new Engine(horsepower); // Engine created within Car } public void StartCar() { Console.WriteLine($"{Model} is starting."); CarEngine.Start(); } } public class CompositionExample { public static void Main() { Car car = new Car("Toyota Corolla", 120); car.StartCar(); } }
Explanation:
- Here, the Car class has an Engine object as part of its structure.
- The Engine is created when Car is created, and it would typically be destroyed along with Car, making this a composition relationship.
Output:
Toyota Corolla is starting. Engine with 120 HP started.
4. Practical Examples of Aggregation
Example 1: University and Students
A University can aggregate multiple Student objects. Each Student exists independently of the University, making this an aggregation relationship.
using System; using System.Collections.Generic; public class Student { public string Name { get; set; } public Student(string name) { Name = name; } public void DisplayInfo() { Console.WriteLine($"Student Name: {Name}"); } } public class University { public string UniversityName { get; set; } public List<Student> Students { get; set; } = new List<Student>(); public University(string universityName) { UniversityName = universityName; } public void AddStudent(Student student) { Students.Add(student); } public void DisplayStudents() { Console.WriteLine($"Students in {UniversityName}:"); foreach (Student student in Students) { student.DisplayInfo(); } } } public class UniversityExample { public static void Main() { University university = new University("State University"); Student student1 = new Student("Alice"); Student student2 = new Student("Bob"); university.AddStudent(student1); university.AddStudent(student2); university.DisplayStudents(); } }
Explanation:
- The University class contains a list of Student objects.
- Students can exist outside of a university, making this an aggregation relationship.
Output:
Students in State University: Student Name: Alice Student Name: Bob
Example 2: Team and Players
A Team aggregates Player objects. Each Player can exist independently of a Team.
using System; using System.Collections.Generic; public class Player { public string Name { get; set; } public string Position { get; set; } public Player(string name, string position) { Name = name; Position = position; } public void DisplayInfo() { Console.WriteLine($"Player: {Name}, Position: {Position}"); } } public class Team { public string TeamName { get; set; } public List<Player> Players { get; set; } = new List<Player>(); public Team(string teamName) { TeamName = teamName; } public void AddPlayer(Player player) { Players.Add(player); } public void DisplayTeam() { Console.WriteLine($"Team: {TeamName}"); foreach (Player player in Players) { player.DisplayInfo(); } } } public class TeamExample { public static void Main() { Team team = new Team("Warriors"); Player player1 = new Player("John", "Forward"); Player player2 = new Player("Mark", "Guard"); team.AddPlayer(player1); team.AddPlayer(player2); team.DisplayTeam(); } }
Explanation:
- The Team aggregates a list of Player objects, with each Player existing independently.
- This is a classic example of aggregation where a team has players, but each player could play for a different team or exist on their own.
Output:
Team: Warriors Player: John, Position: Forward Player: Mark, Position: Guard
Example 3: School and Departments
A School aggregates Department objects. Each Department can exist independently of a School.
using System; using System.Collections.Generic; public class Department { public string DepartmentName { get; set; } public Department(string departmentName) { DepartmentName = departmentName; } public void DisplayInfo() { Console.WriteLine($"Department: {DepartmentName}"); } } public class School { public string SchoolName { get; set; } public List<Department> Departments { get; set; } = new List<Department>(); public School(string schoolName) { SchoolName = schoolName; } public void AddDepartment(Department department) { Departments.Add(department); } public void DisplayDepartments() { Console.WriteLine($"Departments in {SchoolName}:"); foreach (Department department in Departments) { department.DisplayInfo(); } } } public class SchoolExample { public static void Main() { School school = new School("Engineering School"); Department dept1 = new Department("Computer Science"); Department dept2 = new Department("Mechanical Engineering"); school.AddDepartment(dept1); school.AddDepartment(dept2); school.DisplayDepartments(); } }
Explanation:
- The School aggregates
a list of Department objects.
- Each department exists independently, so this is an aggregation relationship.
Output:
Departments in Engineering School: Department: Computer Science Department: Mechanical Engineering
Summary
Aggregation is a useful concept for representing “has-a” relationships where objects are connected but can exist independently. Here’s a recap of key points:
- Aggregation: A “whole-part” relationship where the contained objects can exist independently.
- Implementation: Typically involves defining classes with fields or properties that reference other classes.
- Aggregation vs Composition: In aggregation, the “part” objects can exist independently, while in composition, they are usually created and destroyed with the “whole” object.
- Practical Examples: Aggregation is commonly seen in relationships like Library-Book, University-Student, and Team-Player.
Aggregation helps in building modular and reusable components in C# applications, allowing objects to maintain independence while still being part of a larger structure.