Python || OOP(基础版)类的语法,继承与多态
目录
一、类的基本语法与应用
二、类的属性
三、类的实例
四、继承
4.1 继承顺序
五、多态
5.1 多态的几种实现方式
5.1.1 鸭子类型
5.1.2 通过继承实现多态
5.1.3 使用抽象类强化接口约束
5.1.4 运算符重载
一、类的基本语法与应用
类class,可以理解为一个自定义的数据类型,与基本数据类型int、float的作用和用法相似。
下面是类class的基本语法框架:
class myClass(): #类名a = 1 #字段/类属性def show(self): #类方法print(self.a) #输出实例属性m = myClass() #创建类的实例对象
print(m.a) #调用类的字段
m.show() #调用类方法
一般来说,一个类包含:类名、参数、字段、类方法。使用类的时候,创建该类的实例对象,通过实例对象调用该类的属性和方法。
二、类的属性
类的属性主要包含类的字段和类方法。字段正常定义即可;类方法的参数必须多一个强制首参“self”,用于引用调用该方法的实例对象。
class myClass:def method(self, x):self.x = x
三、类的实例
# 类的定义:类对象的创建
class User:name = 'noname'age = 18def setName(self, name):self.name = namedef setAge(self, age):self.age = agedef show(self):print(self.name, self.age)# 创建对象
lml = User()
# 修改对象属性
lml.setAge(28)
lml.setName('LML')
#展示实例属性
lml.show()# 为类创建新属性
User.sex = 'male'# 对象继承类的属性,方法也可看做类的属性
print(lml.sex)
创建实例对象后,使用实例对象给属性进行赋值的时候,这个值就是赋给实例对象本身的属性,而不是类的属性。
四、继承
Python支持继承。功能跟java类似,但在具体使用上不同。
下面实现了一个基础的继承:
#父类
class Super: def __init__(self, x):self.x = x
#子类
class Sub(Super):def __init__(self, x, y): #重写父类方法Super.__init__(self, x) #沿用父类的相同属性self.y = yI = Sub(1, 2)
- 父类名字在类名后的括号中,可以有多个父类。
- 类可以继承父类的所有属性
现在创建了一个实例对象,调用了其中一个字段属性。该实例所属的类有多层父类,而且多个父类都有该字段,会优先调用谁的字段呢?来看看下面的解释 ↓
4.1 继承顺序
一般情况来讲,继承顺序使用“就近原则”,优先调用最近的类属性,但也有一些复杂的情况。
假如现在有A1~A6的六个类,这六个类有继承关系。所有的方法中都含字段“a”,每个类的字段a的值也依次为1~6,那么会优先调用谁的a呢?
将这六个类的继承关系分为两种,一种是有一个共同的父类,另一种是没有共同的父类。
下面是第一种情况,有公共父类,a的优先调用次序如红色数字所示:
第二种情况如图所示:
五、多态
多态,也就是“多种形态”,是指同一个操作在作用于不同对象的时候,会有不同的解释,产生不同的结果,符合 “接口一致性” 和 “行为差异化” 。
5.1 多态的几种实现方式
5.1.1 鸭子类型
python的多态奉行“鸭子原则”——如果它走起来像鸭子,叫起来也像鸭子,那么它就是鸭子。
这也是python多态的灵魂,不要求有相同的父类,只要求有相应的方法。
# 定义两个完全无关的类
class Dog:def speak(self):return "汪汪!"
class Car:def speak(self):return "滴滴!"# 定义一个函数,它不关心对象是什么类型
# 只关心对象是否有 speak() 方法
def make_sound(x):return x.speak()# 创建对象
dog = Dog()
car = Car()# 同样的函数,处理不同类型的对象
print(make_sound(dog)) # 输出:汪汪!
print(make_sound(car)) # 输出:滴滴!
5.1.2 通过继承实现多态
这种跟java比较像,是通过子类重写父类方法实现多态。
class Animal:"""动物基类"""def speak(self):print('所有动物都会叫')class Dog(Animal):def speak(self):print('汪')class Cat(Animal):def speak(self):print('喵')if __name__ == '__main__':Animal().speak()Dog().speak()Cat().speak()
在上面这段代码中,Dog类和Cat的父类都是Animal,且都重写了父类中的speak方法,输出不同的结果,这就是多态的体现。
5.1.3 使用抽象类强化接口约束
抽象类是一个不能被实例化的类,在这里的主要目的是能够强制子类实现其父类一些特定的方法。
先来大概讲讲抽象基类abc的基本语法结构:
from abc import ABC, abstractmethod #引用抽象类class 抽象基类名(ABC): # 必须继承 ABC@abstractmethod #装饰器,表示子类必须要实现这个方法def 必须实现的方法(self):pass@abstractmethoddef 另一个必须实现的方法(self):pass
下面是一个更加具体的例子:
from abc import ABC, abstractmethod# 创建抽象基类
class Animal(ABC): # 继承 ABC@abstractmethod # 标记为"必须实现的方法"def speak(self):pass # 继承抽象基类 Animal
class Dog(Animal):# 必须实现 speak() 方法,否则会报错!def speak(self):return "汪汪!"class Cat(Animal):def speak(self):# 必须实现 speak() 方法,否则会报错!return "喵喵!"# 这个类没有实现 speak(),将会报错
class BadAnimal(Animal):pass # 使用
dog = Dog()
cat = Cat()
print(dog.speak()) # 汪汪!
print(cat.speak()) # 喵喵!# 尝试创建 BadAnimal 会报错
# bad = BadAnimal()
5.1.4 运算符重载
Python 中的运算符(如 +
, -
, *
,等)也是多态的,这些实际上是调用了对象内部的特殊方法(如 __add__
, __len__
)。
下面是一个具体的示例,实现了在一个平面坐标内点的加法操作:
class Point:def __init__(self, x, y):# 初始化点的坐标self.x = xself.y = ydef __add__(self, other):# 重载 + 运算符,实现两个点坐标相加new_x = self.x + other.xnew_y = self.y + other.yreturn Point(new_x, new_y)def __str__(self):# 定义对象的字符串表示形式return f"({self.x}, {self.y})"# 创建两个Point对象
point1 = Point(1, 2) #点1坐标是(1,2)
point2 = Point(3, 4) #点2坐标是(3,4)# 使用重载的 + 运算符,这里体现了多态
result = point1 + point2
print(result)