Python面向对象之组合

组合

【一】什么是组合

  • 组合是通过将不同的类或模块组合在一起,创建一个新的类来实现的机制。这意味着一个类的对象可以包含其他类的对象作为其部分,通过组合这些部分来实现整体的功能。

【二】组合与继承的区别

  • 继承(Inheritance)和组合(Composition)是两种不同的代码复用机制,它们在面向对象编程中有着不同的实现和影响。
    1. 继承(Inheritance):
      • 定义: 继承是通过创建新类,基于现有类的属性和方法来构建的机制。子类继承了父类的特性,可以使用父类的属性和方法,并且可以在子类中添加、修改或扩展这些特性。
      • 关系: 继承通常表示 "is-a" 关系,即子类是父类的一种类型。例如,如果有一个Vehicle类,那么CarBicycle等子类可以继承自Vehicle,因为它们都是交通工具。
    2. 组合(Composition):
      • 定义: 组合是通过将不同的类或模块组合在一起,创建一个新的类来实现的机制。这意味着一个类的对象可以包含其他类的对象作为其部分,通过组合这些部分来实现整体的功能。
      • 关系: 组合通常表示 "has-a" 关系,即一个对象包含另一个对象。例如,一个Car对象可能包含一个引擎(Engine)对象、轮胎(Tire)对象等,通过组合这些对象,实现了汽车的功能。
  • 区别:
    • 代码复用: 继承可以在子类中重用父类的代码,但有时可能导致过度耦合和继承链的问题。组合通过将不同的模块组合在一起,提供了更灵活的代码复用机制,减少了耦合。
    • 关系: 继承建立了 "is-a" 关系,表示子类是父类的一种类型。组合建立了 "has-a" 关系,表示一个对象包含另一个对象。

【三】代码解释

【1】交通工具

class Vehicle():
def __init__(self, color, speed, tyre_num):
# 交通工具都有的属性【并不严谨奥,只是演示】
self.color = color # 颜色
self.speed = speed # 时速
self.tyre_num = tyre_num # 轮胎数量
class Tyre(): # 轮胎
def __init__(self, size, price):
self.size = size
self.price = price
'''根据轮胎实例化出来两个轮胎对象'''
car_tyre = Tyre('24inch', 2000) # 汽车轮胎参数
bicycle_tyre = Tyre('28inch', 300) # 自行车轮胎参数
class Car(Vehicle):
# 汽车是【is】交通工具
def __init__(self, color, speed, tyre_num, consume):
# 汽车继承交通工具所需要的参数
super().__init__(color, speed, tyre_num)
self.consume = consume # 消耗的东西
self.tyre = car_tyre # 汽车有【has】汽车轮胎
'''同样,可以直接实例化对象'''
# self.tyre = Tyre('24inch', 2000)
class Bicycle(Vehicle):
# 自行车是【is】交通工具
def __init__(self, color, speed, tyre_num, consume):
# 自行车继承交通工具所需要的参数
super().__init__(color, speed, tyre_num)
self.consume = consume # 消耗的东西
self.tyre = bicycle_tyre # 自行车有【has】自行车轮胎
'''同样,可以直接实例化对象'''
# self.tyre = Tyre('28inch', 300)
car = Car('red', '120km/h', 4, 'oil')
bicycle = Bicycle('yellow', '60km/h', 2, 'manpower')
print(car.__dict__)
# {'color': 'red', 'speed': '120km/h', 'tyre_num': 4, 'consume': 'oil', 'tyre': <__main__.Tyre object at 0x00000214913D3FD0>}
print(bicycle.__dict__)
# {'color': 'yellow', 'speed': '60km/h', 'tyre_num': 2, 'consume': 'manpower', 'tyre': <__main__.Tyre object at 0x00000214913D3E80>}
print(car.tyre.price) # 2000 # 可以拿到汽车轮胎的具体参数
print(bicycle.tyre.price) # 300 # 可以拿到自行车轮胎的具体参数
  • 轮胎与自行车/汽车 就相当于组合了

【2】学校信息系统

class Course:
def __init__(self, name, period, price):
self.name = name
self.period = period
self.price = price
def __str__(self):
return f"""
课程名称:{self.name}
课程周期:{self.period}
课程价格:{self.price}
"""
class School:
school = "OldBoy"
address = 'SH'
class Person(School):
def __init__(self, name, age):
self.name = name
self.age = age
python = Course('python', '6mon', 10000)
linux = Course('linux', '3mon', 20000)
# Teacher类基于继承来重用Person的代码
# 基于组合来重用Course类的代码
class Teacher(Person):
def __init__(self, name, age, course=None):
super().__init__(name, age)
self.course = course
class Student(Person):
def __init__(self, name, age, class_num):
super().__init__(name, age)
self.class_num = class_num
class Admin(Person):
def __init__(self, name, age, level):
super().__init__(name, age)
self.level = level
stu1 = Student('user001', 15, '1-1')
stu2 = Student('user002', 14, '1-2')
# 将python对象作为course参数传入
tea1 = Teacher('tea001', 28, [python])
tea2 = Teacher('tea002', 23, [python, linux])
print(tea1.__dict__) # {'name': 'tea001', 'age': 28, 'course': [<__main__.Course object at 0x00000216CB087FD0>]}
print(tea2.__dict__) # {'name': 'tea002', 'age': 23, 'course': [<__main__.Course object at 0x00000216CB087FD0>, <__main__.Course object at 0x00000216CB087D60>]}
for i in tea1.course:
print('tea1')
print(i)
for i2 in tea2.course:
print('tea2')
print(i2)

【2】流浪图书管理系统

  • 其中没有显式的使用组合,但是我觉得很巧妙
class Book:
def __init__(self, name, author, comment, state=0):
self.name = name
self.author = author
self.comment = comment
self.state = state
def __str__(self):
status = '未借出'
if self.state == 1:
status = '已借出'
return '名称:《%s》 作者:%s 推荐语:%s\n状态:%s ' % (self.name, self.author, self.comment, status)
class BookManager:
books = []
def __init__(self):
book1 = Book('惶然录', '费尔南多·佩索阿',
'一个迷失方向且濒于崩溃的灵魂的自我启示,一首对默默无闻、失败、智慧、困难和沉默的赞美诗。')
book2 = Book('以箭为翅', '简媜',
'调和空灵文风与禅宗境界,刻画人间之缘起缘灭。像一条柔韧的绳子,情这个字,不知勒痛多少人的心肉。')
book3 = Book('心是孤独的猎手', '卡森·麦卡勒斯',
'我们渴望倾诉,却从未倾听。女孩、黑人、哑巴、醉鬼、鳏夫的孤独形态各异,却从未退场。', 1)
self.books.append(book1)
self.books.append(book2)
self.books.append(book3)
def menu(self):
print(
'欢迎使用流浪图书管理系统,每本沉默的好书都是一座流浪的岛屿,希望你有缘发现并着陆,为精神家园找到一片栖息地。\n')
while True:
print('1.查询所有书籍\n2.添加书籍\n3.借阅书籍\n4.归还书籍\n5.退出系统\n')
choice = int(input('请输入数字选择对应的功能:'))
if choice == 1:
self.show_all_book()
elif choice == 2:
self.add_book()
elif choice == 3:
self.lend_book()
elif choice == 4:
self.return_book()
else:
print('感谢使用!愿你我成为爱书之人,在茫茫书海里相遇。')
break
def show_all_book(self):
print('书籍信息如下:')
for book in self.books:
print(book)
print('')
def add_book(self):
new_name = input('请输入书籍名称:')
new_author = input('请输入作者名称:')
new_comment = input('请输入书籍推荐语:')
new_book = Book(new_name, new_author, new_comment)
self.books.append(new_book)
print('书籍录入成功!\n')
def check_book(self, name):
for book in self.books:
if book.name == name:
return book
else:
return None
def lend_book(self):
name = input('请输入书籍的名称:')
res = self.check_book(name)
if res != None:
if res.state == 1:
print('你来晚了一步,这本书已经被借走了噢')
else:
print('借阅成功,借了不看会变胖噢~')
res.state = 1
else:
print('这本书暂时没有收录在系统里呢')
def return_book(self):
name = input('请输入归还书籍的名称:')
res = self.check_book(name)
if res == None:
print('没有这本书噢,你恐怕输错了书名~')
else:
if res.state == 0:
print('这本书没有被借走,在等待有缘人的垂青呢!')
else:
print('归还成功!')
res.state = 0
manager = BookManager()
manager.menu()
posted @   Lea4ning  阅读(62)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示