【成人版python基础入门】第四章 深入面向对象——对象也有“朋友圈”
深入面向对象——对象也有“朋友圈”
在上一篇教程中,我们初步了解了面向对象编程(Object-Oriented Programming, OOP)的基本概念,如类和对象、属性和方法。现在,我们将进一步探索面向对象编程的高级概念:继承、多态和封装。通过这些概念,你将能够创建出更加复杂和有趣的程序,让你的对象不再孤单,拥有更多的多样性和安全性。
继承让对象不再孤单
什么是继承
继承(Inheritance)是面向对象编程中的一个重要概念,它允许一个类(子类)继承另一个类(父类)的属性和方法。通过继承,子类可以重用父类的代码,同时还可以添加新的属性和方法,或者修改已经继承的方法。
继承的作用
继承的主要作用是代码重用和扩展。通过继承父类,子类可以不需要重复定义父类中已有的属性和方法,从而减少代码冗余,提高代码的可维护性。同时,子类可以添加或修改父类的属性和方法,使其更适合特定的需求。
风趣的例子
假设你是一名宠物店老板,正在学习如何管理各种宠物。你有一个宠物的基本类,然后通过继承这个基本类来创建更具体的宠物类。
# 宠物基本类
class Pet:
def __init__(self, name, age):
self.name = name
self.age = age
def eat(self):
print(f"{self.name} 正在吃东西。")
def play(self):
print(f"{self.name} 正在玩耍。")
def sleep(self):
print(f"{self.name} 正在睡觉。")
# 宠物猫类,继承自 Pet 类
class Cat(Pet):
def __init__(self, name, age, color):
super().__init__(name, age)
self.color = color
def meow(self):
print(f"{self.name} 发出可爱的喵喵声。")
# 宠物狗类,继承自 Pet 类
class Dog(Pet):
def __init__(self, name, age, breed):
super().__init__(name, age)
self.breed = breed
def bark(self):
print(f"{self.name} 发出响亮的汪汪声。")
在这个例子中,Pet
类是父类,定义了所有宠物共有的属性和方法。Cat
和 Dog
类是子类,分别继承了 Pet
类的属性和方法,并添加了特定于猫和狗的方法。
代码详解
-
父类
Pet
:class Pet: def __init__(self, name, age): self.name = name self.age = age def eat(self): print(f"{self.name} 正在吃东西。") def play(self): print(f"{self.name} 正在玩耍。") def sleep(self): print(f"{self.name} 正在睡觉。")
Pet
类定义了宠物的name
和age
属性,以及eat
、play
和sleep
方法。 -
子类
Cat
:class Cat(Pet): def __init__(self, name, age, color): super().__init__(name, age) self.color = color def meow(self): print(f"{self.name} 发出可爱的喵喵声。")
Cat
类继承了Pet
类,并添加了color
属性和meow
方法。使用super()
调用父类的__init__
方法来初始化从父类继承的属性。 -
子类
Dog
:class Dog(Pet): def __init__(self, name, age, breed): super().__init__(name, age) self.breed = breed def bark(self): print(f"{self.name} 发出响亮的汪汪声。")
Dog
类继承了Pet
类,并添加了breed
属性和bark
方法。同样使用super()
调用父类的__init__
方法来初始化从父类继承的属性。
多态让你的对象拥有多样性
什么是多态
多态(Polymorphism)是指不同的对象可以以不同的方式响应相同的方法调用。在面向对象编程中,多态通常通过方法重写(Method Overriding)和接口(Interface)实现。
多态的含义
多态的含义是“多种形态”,即一个方法在不同的对象上有不同的实现。通过多态,我们可以在不改变调用方式的情况下,实现不同的功能。
多态的实际应用
多态的一个常见应用场景是使用同一个方法来处理不同类型的对象。这使得代码更加灵活和通用。
幽默的例子
假设你是一名音乐老师,正在教不同的学生演奏乐器。你有一个基本的乐器类,然后通过继承这个类来创建不同的乐器子类。每个乐器子类都有自己的演奏方法,但你可以用同一个方法来指挥所有学生演奏。
# 乐器基本类
class Instrument:
def play(self):
print("正在演奏乐器。")
# 钢琴类,继承自 Instrument 类
class Piano(Instrument):
def play(self):
print("叮叮叮,正在弹钢琴。")
# 小提琴类,继承自 Instrument 类
class Violin(Instrument):
def play(self):
print("吱吱吱,正在拉小提琴。")
# 鼓类,继承自 Instrument 类
class Drum(Instrument):
def play(self):
print("咚咚咚,正在打鼓。")
# 定义一个乐队类,包含多个乐器对象
class Band:
def __init__(self):
self.instruments = []
def add_instrument(self, instrument):
self.instruments.append(instrument)
def play_music(self):
for instrument in self.instruments:
instrument.play()
# 创建乐器对象
piano = Piano()
violin = Violin()
drum = Drum()
# 创建乐队对象并添加乐器
my_band = Band()
my_band.add_instrument(piano)
my_band.add_instrument(violin)
my_band.add_instrument(drum)
# 演奏音乐
my_band.play_music()
代码详解
-
基本类
Instrument
:class Instrument: def play(self): print("正在演奏乐器。")
Instrument
类定义了一个play
方法,这是一个通用的方法。 -
子类
Piano
:class Piano(Instrument): def play(self): print("叮叮叮,正在弹钢琴。")
Piano
类继承了Instrument
类,重写了play
方法,使其更适合钢琴的演奏。 -
子类
Violin
:class Violin(Instrument): def play(self): print("吱吱吱,正在拉小提琴。")
Violin
类继承了Instrument
类,重写了play
方法,使其更适合小提琴的演奏。 -
子类
Drum
:class Drum(Instrument): def play(self): print("咚咚咚,正在打鼓。")
Drum
类继承了Instrument
类,重写了play
方法,使其更适合鼓的演奏。 -
乐队类
Band
:class Band: def __init__(self): self.instruments = [] def add_instrument(self, instrument): self.instruments.append(instrument) def play_music(self): for instrument in self.instruments: instrument.play()
Band
类包含一个列表instruments
,用于存储乐器对象。add_instrument
方法用于添加乐器,play_music
方法用于遍历列表并调用每个乐器的play
方法。
运行结果
假设你运行了上面的代码,程序会创建一个乐队对象,并添加三个不同类型的乐器对象。当乐队开始演奏时,不同的乐器会有不同的演奏方式。
叮叮叮,正在弹钢琴。
吱吱吱,正在拉小提琴。
咚咚咚,正在打鼓。
封装保护对象的“秘密”
什么是封装
封装(Encapsulation)是指将对象的属性和方法包装在一起,形成一个独立的单位,并限制外部代码对对象内部数据的直接访问。封装可以保护对象的内部状态,防止外部代码随意修改,提高代码的安全性和可维护性。
封装的使用方法
在 Python 中,封装可以通过以下几种方式实现:
- 公有属性和方法:没有任何前缀,可以直接访问。
- 受保护属性和方法:使用单下划线前缀
_
,表示这些属性和方法是受保护的,不应该在类的外部直接访问。 - 私有属性和方法:使用双下划线前缀
__
,表示这些属性和方法是私有的,只能在类的内部访问。
实际代码示例
假设我们要创建一个更复杂的银行账户类,包含受保护和私有属性和方法。
class BankAccount:
# 类属性
bank_name = "WeTab Bank"
def __init__(self, owner, balance=0.0):
self.owner = owner
self.balance = balance
self._secret_key = "123456" # 受保护的属性
self.__private_pin = "7890" # 私有的属性
def deposit(self, amount):
self.balance += amount
print(f"存款成功,当前余额为: {self.balance}")
def withdraw(self, amount):
if amount > self.balance:
print("余额不足,取款失败。")
else:
self.balance -= amount
print(f"取款成功,当前余额为: {self.balance}")
def _check_secret(self, key):
if key == self._secret_key:
return True
else:
print("密钥错误,无法进行操作。")
return False
def __check_pin(self, pin):
if pin == self.__private_pin:
return True
else:
print("PIN错误,无法进行操作。")
return False
def transfer(self, amount, recipient, key, pin):
if self._check_secret(key) and self.__check_pin(pin):
if amount > self.balance:
print("余额不足,转账失败。")
else:
self.balance -= amount
recipient.balance += amount
print(f"转账成功,当前余额为: {self.balance},接收者余额为: {recipient.balance}")
else:
print("无法完成转账。")
# 实例化银行账户对象
alice_account = BankAccount("Alice", 1000.0)
bob_account = BankAccount("Bob", 500.0)
# 与银行账户互动
alice_account.deposit(500.0)
alice_account.transfer(200.0, bob_account, "123456", "7890")
# 尝试访问受保护和私有属性
print(alice_account._secret_key) # 输出:123456
# print(alice_account.__private_pin) # 会报错,因为 __private_pin 是私有的
代码详解
-
类属性:
bank_name = "WeTab Bank"
bank_name
是一个类属性,所有BankAccount
对象共享这个属性。 -
初始化方法:
def __init__(self, owner, balance=0.0): self.owner = owner self.balance = balance self._secret_key = "123456" # 受保护的属性 self.__private_pin = "7890" # 私有的属性
__init__
方法在创建对象时自动调用,初始化对象的属性。_secret_key
是受保护的属性,__private_pin
是私有的属性。 -
普通方法:
def deposit(self, amount): self.balance += amount print(f"存款成功,当前余额为: {self.balance}") def withdraw(self, amount): if amount > self.balance: print("余额不足,取款失败。") else: self.balance -= amount print(f"取款成功,当前余额为: {self.balance}")
deposit
和withdraw
是普通方法,用于处理存款和取款。 -
受保护方法:
def _check_secret(self, key): if key == self._secret_key: return True else: print("密钥错误,无法进行操作。") return False
_check_secret
是受保护的方法,用于检查密钥是否正确。 -
私有方法:
def __check_pin(self, pin): if pin == self.__private_pin: return True else: print("PIN错误,无法进行操作。") return False
__check_pin
是私有的方法,用于检查 PIN 是否正确。 -
转账方法:
def transfer(self, amount, recipient, key, pin): if self._check_secret(key) and self.__check_pin(pin): if amount > self.balance: print("余额不足,转账失败。") else: self.balance -= amount recipient.balance += amount print(f"转账成功,当前余额为: {self.balance},接收者余额为: {recipient.balance}") else: print("无法完成转账。")
transfer
方法用于处理转账,需要提供正确的密钥和 PIN。
运行结果
假设你运行了上面的代码,程序会创建两个银行账户对象,并处理存款和转账操作。尝试直接访问受保护和私有属性时,程序会分别允许和拒绝。
存款成功,当前余额为: 1500.0
转账成功,当前余额为: 1300.0,接收者余额为: 700.0
123456
代码样例:建立一个多宠物的家庭
为了更好地展示面向对象编程的灵活性和优势,我们来创建一个多宠物的家庭,看看家里宠物们的“社交生活”。
定义基本宠物类
class Pet:
def __init__(self, name, age):
self.name = name
self.age = age
def eat(self):
print(f"{self.name} 正在吃东西。")
def play(self):
print(f"{self.name} 正在玩耍。")
def sleep(self):
print(f"{self.name} 正在睡觉。")
def greet(self, other_pet):
print(f"{self.name} 和 {other_pet.name} 互相打招呼。")
定义具体的宠物类
class Cat(Pet):
def __init__(self, name, age, color):
super().__init__(name, age)
self.color = color
def meow(self):
print(f"{self.name} 发出可爱的喵喵声。")
class Dog(Pet):
def __init__(self, name, age, breed):
super().__init__(name, age)
self.breed = breed
def bark(self):
print(f"{self.name} 发出响亮的汪汪声。")
class Bird(Pet):
def __init__(self, name, age, species):
super().__init__(name, age)
self.species = species
def chirp(self):
print(f"{self.name} 发出清脆的鸟鸣。")
定义家庭类
class Family:
def __init__(self):
self.pets = []
def add_pet(self, pet):
self.pets.append(pet)
print(f"{pet.name} 加入了家庭。")
def feed_all_pets(self):
for pet in self.pets:
pet.eat()
def play_with_all_pets(self):
for pet in self.pets:
pet.play()
def let_all_pets_sleep(self):
for pet in self.pets:
pet.sleep()
def have_pets_greet_each_other(self):
for i, pet1 in enumerate(self.pets):
for j, pet2 in enumerate(self.pets):
if i < j:
pet1.greet(pet2)
创建家庭并添加宠物
# 创建宠物对象
kitteh = Cat("Kitteh", 3, "white")
milo = Cat("Milo", 2, "black")
rocky = Dog("Rocky", 5, "Labrador")
chirpy = Bird("Chirpy", 1, "Canary")
# 创建家庭对象并添加宠物
my_family = Family()
my_family.add_pet(kitteh)
my_family.add_pet(milo)
my_family.add_pet(rocky)
my_family.add_pet(chirpy)
与宠物互动
# 饲养所有宠物
my_family.feed_all_pets()
my_family.play_with_all_pets()
my_family.let_all_pets_sleep()
# 让宠物们互相打招呼
my_family.have_pets_greet_each_other()
运行结果
假设你运行了上面的代码,程序会创建一个家庭对象,并添加四个宠物对象。然后,程序会模拟喂食、玩耍、睡觉和宠物之间的互动。
Kitteh 加入了家庭。
Milo 加入了家庭。
Rocky 加入了家庭。
Chirpy 加入了家庭。
Kitteh 正在吃东西。
Milo 正在吃东西。
Rocky 正在吃东西。
Chirpy 正在吃东西。
Kitteh 正在玩耍。
Milo 正在玩耍。
Rocky 正在玩耍。
Chirpy 正在玩耍。
Kitteh 正在睡觉。
Milo 正在睡觉。
Rocky 正在睡觉。
Chirpy 正在睡觉。
Kitteh 和 Milo 互相打招呼。
Kitteh 和 Rocky 互相打招呼。
Kitteh 和 Chirpy 互相打招呼。
Milo 和 Rocky 互相打招呼。
Milo 和 Chirpy 互相打招呼。
Rocky 和 Chirpy 互相
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)