[重学Python]Day7 面向对象编程:封装、继承、多态
一、面向对象编程的特性
面向对象编程的三大特性,封装、继承、多态
封装就是把客观事物封装成抽象的类,并隐藏实现细节,使得代码模块化。比如在上篇文章(Day 6)中,我们把”汽车“这个客观事物封装成一个类,这个类有颜色、品牌、速度等,下文我们会提到方法,而这些属性和方法的具体实现则被隐藏起来,使用者只需要知道这个类有哪些属性和方法,不需要知道这些方法是如何实现的。
2、继承
继承是面向对象编程的另一个重要特性,它提供了一种无需重写、使用现有类的所有功能并进行扩展的能力。比如,我可以定义个”电车“类,它继承了”Car“,就自动拥有了”Car“类的所有属性和方法,比如颜色、品牌等。然后我们还可以在”电车“类上增加一些新的属性和方法,比如电池容量、充电方法等。
3、多态
多态是指同一操作用于不同的对象,可以有不同的解释,产生不同的执行结果。比如,我们定义了一个”Car“类,它有一个”启动“方法,然后我们又定义了一个”电车“类,它继承了”Car“类,也有一个”启动“方法,但是”电车“类的”启动“方法的实现可能与”Car“类的不同,这就是多态。
二、静态方法和类方法
之前,我们在类中定义的方法都是对象方法,也就是说这些方法都是发送给对象的消息,实际上,我们写在类中的方法不需要都是对象方法,例如我们顶一个一个三角形类,通过传入三条边长来构造三角形,并提供计算周长和面积的方法,但是传入的三条边长未必能构造出三角形对象,因此我们可以先写一个方法来验证三条边长是否可以构成三角形,这个方法很显然不是对象方法,因为在调用这个方法时三角形对象尚未创建出来,所以这个方法是属于三角形类而不是属于三角形对象的,我们可以使用静态方法来解决这类问题。
from math import sqrt
class Triangle(object):
def __init__(self,a,b,c):
self.a = a
self.b = b
self.c = c
def is_valid(a, b, c):
return a + b > c and b + c > a and a + c > b
def perimeter(self):
return self.a + self.b + self.c
def area(self):
half = self.perimeter() / 2
return sqrt(half * (half - self.a) * (half - self.b) * (half - self.c))
def main():
a , b, c = 6, 8, 10
if Triangle.is_valid(a,b,c):
t = Triangle(a,b,c)
print(t.perimeter())
# 也可以通过给类发消息来调用对象方法,但是要传入接收消息的对象作为参数
print(Triangle.area(t))
else:
print("Unable to form a Triangle")
if __name__ == '__main__':
main()
和静态方法比较类似,Python还可以在类中定义类方法,类方法的第一个参数约定名为cls,它代表的是当前类相关的信息的对象(类本身也是一个对象),通过这个参数我们可以获取和类相关的信息并且可以创建出来的对象。
from time import time, localtime, sleep
class Clock(object):
"""数字时钟"""
def __init__(self, hour=0, minute=0, second=0):
self._hour = hour
self._minute = minute
self._second = second
@classmethod
def now(cls):
ctime = localtime(time())
return cls(ctime.tm_hour, ctime.tm_min, ctime.tm_sec)
def run(self):
"""走字"""
self._second += 1
if self._second == 60:
self._second = 0
self._minute += 1
if self._minute == 60:
self._minute = 0
self._hour += 1
if self._hour == 24:
self._hour = 0
def show(self):
"""显示时间"""
return '%02d:%02d:%02d' % \
(self._hour, self._minute, self._second)
def main():
# 通过类方法创建对象并获取系统时间
clock = Clock.now()
while True:
print(clock.show())
sleep(1)
clock.run()
if __name__ == '__main__':
main()
三、类之间的关系
类和类之间存在三种关系:is-a has-a use-a
1、is-a
也叫做继承和繁华,比如汽车和交通工具,人和动物的关系都属于继承关系
2、has-a
也叫做关联,比如学生和所在学院,显卡和主机都属于关联。关联关系如果是整体和部分的关联,那么叫做聚合关系,如果整体进一步负责了部分的生命周期,就是整体和部分是不可分割的,也叫做合成关系
3、use-a
也叫做依赖,比如一个司机有一个驾驶的行为(方法),其中使用到了汽车,那么司机和汽车的关系就是依赖关系
利用类之间的这些关系,我们可以在已有类的基础上来完成某些操作,也可以在已有类的基础上创建新的类,这些都是实现代码复用的重要手段。复用现有的代码不仅可以减少开发的工作量,也有利于代码的管理和维护,这是我们在日常工作中都会使用到的技术手段。
四、继承
在已有类的基础上创建新类,就是让一个类从另一个类那里将属性和方法直接继承下来,从而减少重复代码的编写。提供继承信息的叫做父类,也叫做超类和基类,得到信息的称为子类,也叫派生类和衍生类。子类除了继承父类提供的属性和方法,还可以定义自己特有的属性和方法,所以子类比父类有更多的能力。
class Person(object):
def __init__(self,name,age):
self.name = name
self.age = age
def name(self):
return self.name
def age(self):
return self.age()
def eatBBQ(self):
print('%s正在吃阿根廷烤肉.' % self.name)
class Football_Player(Person):
def __init__(self, name, age, title):
super().__init__(name, age)
self.title = title
def title(self):
return self.title
def title(self, title):
self.title = title
def workfor(self, team):
print('%s%s效力于%s.' % (self.title, self.name, team))
def main():
fb = Football_Player('Messi',37,'Goat')
fb.workfor('迈阿密国际')
fb.eatBBQ()
if __name__ == '__main__':
main()
输出:
GoatMessi效力于迈阿密国际.
Messi正在吃阿根廷烤肉.
五、重写和多态
子类在继承了父类的方法后,可以对父类已有的方法给出新的版本,这个过程叫做方法的重写(override)。通过重写,可以让父类的同一个行为在子类中出现不同的版本,当调用这个重写后的子类方法时,不同的子类对象会有不同的行为,这个就是多态。
from abc import ABCMeta, abstractmethod
# 在Python的abc模块中,ABC和ABCMeta是两个关键类,用于创建抽象基类(Abstract Base Class)。
# 通过将ABCMeta作为元类,可以在类定义阶段对类进行检查和修饰。
# ABCMeta通过在类定义中使用metaclass参数或在类的基类列表中包含ABCMeta来指定。
# ABCMeta元类提供了一些功能,例如检查子类是否实现了抽象方法、注册具体实现类等。
class Pet(object, metaclass=ABCMeta):
"""宠物"""
def __init__(self, nickname):
self._nickname = nickname
@abstractmethod
def make_voice(self):
"""发出声音"""
pass
class Dog(Pet):
"""狗"""
def make_voice(self):
print('%s: 汪汪汪...' % self._nickname)
class Cat(Pet):
"""猫"""
def make_voice(self):
print('%s: 喵...喵...' % self._nickname)
def main():
pets = [Dog('大黄'), Cat('咪咪'), Dog('二黄')]
for pet in pets:
pet.make_voice()
if __name__ == '__main__':
main()
Pet是一个抽象类,抽象类的存在就是为了让其他类去继承它,Python从语法层面讲没有java那样对抽象类的支持,所以我们通过abc
模块的ABCMeta
元类和abstractmethod
包装器来达到抽象类的效果,如果一个类中存在抽象方法,那么这个类不能够创建对象(实例化)。上文中,Dog和Cat对Pet中的voice方法进行了重写,当我们在main中调用该方法时,这个方法就表现为多态,即同样的方法做了不同的事情。
- 点赞
- 收藏
- 关注作者
评论(0)