Как композиция и агрегация связаны друг с другом?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Композиция и агрегация в объектно-ориентированном программировании
Композиция и агрегация — это два типа отношений между объектами в ООП, обе относятся к принципу композиции вместо наследования (Composition over Inheritance). Хотя они похожи, между ними есть важные различия.
1. Основное различие
Агрегация — это отношение типа "часть-целое", где части могут существовать независимо от целого. Композиция — это более строгое отношение, где части не могут существовать отдельно от целого (жизненный цикл привязан).
# АГРЕГАЦИЯ: части существуют независимо
class Company:
def __init__(self, name, employees):
self.name = name
self.employees = employees # список уже существующих Employee объектов
class Employee:
def __init__(self, name, salary):
self.name = name
self.salary = salary
# Создаем Employee отдельно
employee1 = Employee("Alice", 50000)
employee2 = Employee("Bob", 60000)
# Создаем Company с уже существующими employees
company = Company("TechCorp", [employee1, employee2])
# Employee может существовать без Company
del company
print(employee1.name) # "Alice" — сотрудник существует!
2. Композиция
В композиции целое отвечает за создание и уничтожение своих частей:
class Engine:
def __init__(self, horsepower):
self.horsepower = horsepower
print(f"Engine created with {horsepower} hp")
def __del__(self):
print("Engine destroyed")
class Car:
def __init__(self, brand, horsepower):
self.brand = brand
self.engine = Engine(horsepower) # Car создает Engine
print(f"Car created")
def __del__(self):
print("Car destroyed")
# engine удаляется автоматически при удалении Car
car = Car("BMW", 300)
print("---")
del car # удаляем машину
# Вывод:
# Engine created with 300 hp
# Car created
# ---
# Car destroyed
# Engine destroyed
3. Агрегация
В агрегации целое содержит ссылки на уже существующие объекты:
class Student:
def __init__(self, name, student_id):
self.name = name
self.student_id = student_id
def __del__(self):
print(f"Student {self.name} deleted")
class University:
def __init__(self, name, students):
self.name = name
self.students = students # ссылка на уже существующих студентов
def __del__(self):
print(f"University {self.name} deleted")
# Студенты существуют независимо
student1 = Student("John", 1001)
student2 = Student("Jane", 1002)
university = University("MIT", [student1, student2])
print("---")
del university # удаляем университет
print("---")
# Вывод:
# ---
# University MIT deleted
# ---
# Студенты все еще существуют!
print(student1.name) # John
4. Сравнительная таблица
| Аспект | Агрегация | Композиция |
|---|---|---|
| Тип отношения | Слабое "часть-целое" | Строгое "часть-целое" |
| Жизненный цикл | Независимый | Связанный |
| Существование частей | Могут существовать отдельно | Зависят от целого |
| Пример | Компания и сотрудники | Автомобиль и двигатель |
| Удаление целого | Части остаются | Части удаляются |
5. Диаграмма UML
# АГРЕГАЦИЯ (пустой ромб)
Company ◇────── Employee
(целое) (часть)
# КОМПОЗИЦИЯ (заполненный ромб)
Car ◆────── Engine
(целое) (часть)
6. Практический пример: Библиотека
class Author:
def __init__(self, name):
self.name = name
class Book:
def __init__(self, title, author):
self.title = title
self.author = author # агрегация
print(f"Book {title} created")
def __del__(self):
print(f"Book {self.title} deleted")
class Library:
def __init__(self, name):
self.name = name
self.books = [] # агрегация книг
def add_book(self, book):
self.books.append(book)
def __del__(self):
print(f"Library {self.name} closed")
# Author существует отдельно
author = Author("Tolstoy")
# Book создается с Author (агрегация)
book1 = Book("War and Peace", author)
book2 = Book("Anna Karenina", author)
# Library содержит Books (агрегация)
library = Library("City Library")
library.add_book(book1)
library.add_book(book2)
print("---")
del library
print("---")
# Author и Books все еще существуют!
print(f"{author.name} is still alive")
print(f"Book exists: {book1.title}")
7. Композиция: более строгий пример
class Publisher:
def __init__(self, name):
self.name = name
class Page:
def __init__(self, number, content):
self.number = number
self.content = content
class Document:
def __init__(self, title, publisher):
self.title = title
self.publisher = publisher # агрегация Publisher
self.pages = [] # композиция Pages
def add_page(self, content):
page = Page(len(self.pages) + 1, content) # Document создает Pages
self.pages.append(page)
def __del__(self):
print(f"Document {self.title} destroyed")
# Все pages удаляются с Document
doc = Document("MyBook", Publisher("MyPublisher"))
doc.add_page("Introduction")
doc.add_page("Chapter 1")
print(f"Pages: {len(doc.pages)}")
del doc # Pages удаляются вместе с Document
8. Когда использовать что
# ✅ Используй АГРЕГАЦИЮ когда:
# - Части могут существовать отдельно
# - Части могут принадлежать нескольким целым
class Team:
def __init__(self, members): # members — уже существующие Player объекты
self.members = members
# ✅ Используй КОМПОЗИЦИЮ когда:
# - Части имеют смысл только как часть целого
# - Целое отвечает за создание/удаление частей
class House:
def __init__(self):
self.roof = Roof() # House создает Roof
self.walls = [Wall() for _ in range(4)] # House создает Walls
Ключевые выводы
✅ Композиция — строгое отношение, жизненные циклы привязаны ✅ Агрегация — слабое отношение, независимые жизненные циклы ✅ Композиция "лучше" наследования — используй композицию вместо наследования ✅ DIP — оба паттерна поддерживают принцип инверсии зависимостей ✅ Гибкость — агрегация более гибкая, композиция более надежная
Выбор между ними зависит от семантики вашей предметной области.