🍀 前言
博客地址:
👋 简介
什么是抽象类,抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化。抽象类的本质还是类,指的是一组类的相似性,而接口只强调函数属性的相似性。
抽象类:is-a的关系,属于某种东西的概念
接口类:has-a的关系,属于拥有某种型为
📖 正文
1 抽象类
抽象方法是一种在基类中声明但不提供具体实现的方法。这些方法在基类中只有方法签名,而具体的实现需要在派生类中完成。在Python中,使用abstractmethod
装饰器来标记抽象方法。
1.1 定义抽象类
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
pass
@abstractmethod
def perimeter(self):
pass
Shape
类继承自ABC
,表示这是一个抽象基类,并且使用@abstractmethod
装饰器声明了抽象方法area
和perimeter
。告诉Python解释器,任何继承自Shape
的子类都必须提供area
和perimeter
方法的具体实现。
1.2 对抽象类的继承
class Circle(Shape):
PI = 3.14
def __init__(self, radius):
"""
圆形初始数据
:param radius: 半径
"""
self.radius = radius
def area(self):
"""
圆形面积计算:π * r^2
:return:
"""
return self.radius ** 2 * Circle.PI
def perimeter(self):
"""
圆形周长计算:直径 * π
:return:
"""
return 2 * Circle.PI * self.radius
class Rectangle(Shape):
def __init__(self, width, height):
"""
长方形的初始数据
:param width: 宽
:param height: 长
"""
self.width = width
self.height = height
def area(self):
"""
长方形面积计算:长 * 宽
:return:
"""
return self.width * self.height
def perimeter(self):
"""
长方形周长计算:2 * (长 + 宽)
:return:
"""
return 2 * (self.width + self.height)
定义两个类,分别为圆形类Circle
和长方形类Rectangle
,同时这两个类分别实现了计算面积area
和计算周长perimeter
的方法
2 接口类
接口类的定义和抽象类相同,只不过接口类做为拓展,表示一种has-a的关系,拥有某种行为
2.1 初始类
class Tiger():
def __init__(self):
self.type = '老虎'
def walk(self):
print(f'{self.type}会走路')
def swim(self):
print(f'{self.type}会游泳')
class Monkey():
def __init__(self):
self.type = '猴子'
def walk(self):
print(f'{self.type}会走路')
def climb(self):
print(f'{self.type}会爬树')
class Swan():
def __init__(self):
self.type = '天鹅'
def walk(self):
print(f'{self.type}会走路')
def swim(self):
print(f'{self.type}会游泳')
def fly(self):
print(f'{self.type}会飞行')
定义三个动物类,他们都分别有相同的行为,此时当我们新增一个喜鹊类,如果同样存在飞行属性的动物,就需要定义飞行相关的方法,所以我们可以将相同行为的抽取出来,定义一个接口类,然后进行实现
# 这时新增一个类,同样包含walk和fly行为
class Magpie():
def __init__(self):
self.type = '喜鹊'
def walk(self):
print(f'{self.type}会走路')
def fly(self):
print(f'{self.type}会飞行')
2.2 定义接口类
class IWalk(ABC):
@abstractmethod
def walk(self):
pass
class ISwim(ABC):
@abstractmethod
def swim(self):
pass
class IFly(ABC):
@abstractmethod
def fly(self):
pass
定义三个接口,分别表示三种行为,其中首字母I
,表示这是一个接口类
2.3 对接口类实现
class Tiger(IWalk, ISwim):
def __init__(self):
self.type = '老虎'
def walk(self):
print(f'{self.type}会走路')
def swim(self):
print(f'{self.type}会游泳')
class Monkey(IWalk):
def __init__(self):
self.type = '猴子'
def walk(self):
print(f'{self.type}会走路')
def climb(self):
print(f'{self.type}会爬树')
class Swan(IWalk, ISwim, IFly):
def __init__(self):
self.type = '天鹅'
def walk(self):
print(f'{self.type}会走路')
def swim(self):
print(f'{self.type}会游泳')
def fly(self):
print(f'{self.type}会飞行')
class Magpie(IWalk, IFly):
def __init__(self):
self.type = '喜鹊'
def walk(self):
print(f'{self.type}会走路')
def fly(self):
print(f'{self.type}会飞行')
Tips:
继承了接口类,就必须全部实现接口类中定义的方法
✏️ 总结
- 抽象类和接口类在python中,并没有什么不同,都是用来约束子类中的方法的,只要是抽象类和接口类中被
abstractmethod
装饰的方法,都需要被子类实现; - 当多个类有相同的功能也有不同的功能的时候,应该采用多个接口类来进行分别的约束
- 抽象类 是python中定义类的一种规范,用来约束子类中的方法的。被
abstractmethod
装饰的方法,子类必须实现,否则实例化时报错。 - 接口类 满足接口隔离原则,且完成多继承的约束。如果不按照规范,在调用方法时,报错。