Association is a general relationship between two classes where objects of one class are connected to objects of another class without strong ownership or lifecycle dependency.
- Both objects can exist independently.
- One object can use another object's methods or data.
- Association does not require inheritance.
- Commonly used to model real-world interactions such as Teacher and Student or Customer and Order.
Example:
class Student:
def __init__(self, name):
self.name = name
class Teacher:
def __init__(self, name):
self.name = name
def teach(self, student):
print(self.name, "teaches", student.name)
student = Student("Rahul")
teacher = Teacher("Anita")
teacher.teach(student)
Output
Anita teaches Rahul
Explanation:
- Student and Teacher are independent classes.
- student is an object of Student.
- teacher is an object of Teacher.
- teach() method receives the Student object as an argument.
- Teacher uses Student without inheriting from Student.
Implementing through Object References
An association can also be maintained as an attribute containing another class's object.
class Author:
def __init__(self, name):
self.name = name
class Book:
def __init__(self, title, author):
self.title = title
self.author = author
def show_details(self):
print("Book:", self.title)
print("Author:", self.author.name)
author = Author("R. K. Sharma")
book = Book("Python Basics", author)
book.show_details()
Output
Book: Python Basics Author: R. K. Sharma
Explanation:
- Author and Book are separate classes.
- Author object is passed to Book.
- Book keeps a reference to the Author object.
- Both objects can exist independently.
Types
Unidirectional Association
In this type, only one class knows about or uses the object of another class. The relationship works in one direction.
class Customer:
def __init__(self, name):
self.name = name
class Order:
def __init__(self, order_id):
self.order_id = order_id
self.customer = None
def show_customer(self):
print("Customer:", self.customer.name)
customer = Customer("Amit")
order = Order(101)
order.customer = customer
order.show_customer()
Output
Customer: Amit
Explanation:
- Order stores a reference to Customer.
- Customer does not store a reference to Order.
Bidirectional Association
Here, both classes maintain references to each other, allowing either object to access the other.
class Student:
def __init__(self, name):
self.name = name
self.teacher = None
class Teacher:
def __init__(self, name):
self.name = name
self.student = None
student = Student("Rahul")
teacher = Teacher("Anita")
student.teacher = teacher
teacher.student = student
print(student.name, "is taught by", student.teacher.name)
print(teacher.name, "teaches", teacher.student.name)
Output
Rahul is taught by Anita Anita teaches Rahul
Explanation:
- Student contains a reference to Teacher.
- Teacher also contains a reference to Student.
- Both objects can navigate the relationship.
Association with Multiple Objects
A class can be associated with multiple objects of another class, usually by maintaining a collection of references.
class Student:
def __init__(self, name):
self.name = name
class Teacher:
def __init__(self, name):
self.name = name
self.students = []
def add_student(self, student):
self.students.append(student)
def show_students(self):
for student in self.students:
print(student.name)
teacher = Teacher("Anita")
teacher.add_student(Student("Rahul"))
teacher.add_student(Student("Priya"))
teacher.add_student(Student("Aman"))
teacher.show_students()
Output
Rahul Priya Aman
Explanation:
- Teacher maintains a list of Student objects.
- Multiple Student objects can be associated with one Teacher.
- Each Student remains an independent object.
- This pattern is useful for relationships such as Teacher-Student and Customer-Order.
Association vs Aggregation vs Composition
They all describe relationships between objects, but their strength and ownership differ.
| Relationship | Main idea | Object independence |
|---|---|---|
| Association | Objects interact or use each other | Independent |
| Aggregation | One object has another as a part | Part can exist independently |
| Composition | One object strongly owns another | Part depends on whole |
Note: For detailed coverage of aggregation and composition, refer to Python OOPS - Aggregation and Composition.