Python—第15天—面向对象继承
继承:
对已有的类进行扩展创建出新的类,这个过程就叫继承。
提供继承信息的类叫做父类(超类、基类),得到继承信息的类称为子类(派生类)。
继承是实现代码复用的一种手段。但是千万不要滥用继承!!!!
-
继承是一种is - a关系:
-
a student is a person.
-
a teacher is a person.
-
a programmer is a person.
子类直接从父类继承公共的属性和行为,再添加自己特有的属性和行为,
所以子类一定是比父类更强大的,任何时候都可以用子类对象去替代父类对象。
Python中继承允许多重继承,一个类可以有一个或多个父类。
如果不是必须使用多重继承的场景下,请尽量使用单一继承
继承语法:
class 派生类名(基类名)
创建一个父类:人,子类有:学生、教师、程序员
class Person:
"""人类"""
def __init__(self, name, gender):
"""初始化方法"""
self.name = name
self.gender = gender
def eat(self):
"""吃"""
print(f'{self.name}正在吃饭.')
def sleep(self):
"""睡"""
print(f'{self.name}正在睡觉.')
def play(self, game_name):
"""玩耍"""
print(f'{self.name}正在玩{game_name}.')
class Student(Person):
"""学生"""
def __init__(self, name, gender, grade):
"""初始化方法"""
super().__init__(name, gender)
self.grade = grade
def study(self, course_name):
"""学习"""
print(f'{self.name}正在学习{course_name}.')
class Teacher(Person):
"""教师"""
def __init__(self, name, gender, title):
super().__init__(name, gender)
self.title = title
def teach(self, course_name):
"""授课"""
print(f'{self.name}{self.title}正在讲授{course_name}')
class Programmer(Person):
"""程序员"""
def write_code(self, programming_language):
"""写代码"""
print(f'{self.name}正在用{programming_language}写代码.')
stu = Student('王大锤', True, '五年级')
stu.study('语文')
stu.play('王者荣耀')
stu.eat()
teacher = Teacher('张三', True, '叫兽')
teacher.eat()
teacher.play('斗地主')
teacher.teach('Python程序设计')
programmer = Programmer('小白', True)
programmer.eat()
programmer.play('吃鸡')
programmer . write_code('Python')
如果要限制一个类的对象只能拥有某些属性,可以在类中使用
__slots__
魔法属性
class student:
__slots__ = ('name', 'gender')
在python中继承中的一些特点:
-
1、如果在子类中需要父类的构造方法就需要显式的调用父类的构造方法,或者不重写父类的构造方法。
-
2、在调用基类的方法时,需要加上基类的类名前缀,且需要带上 self 参数变量。区别在于类中调用普通函数 时并不需要带上 self 参数。
-
3、Python 总是首先查找对应类型的方法,如果它不能在派生类中找到对应的方法,它才开始到基类中逐个查找。(先在本类中查找调用的方法,找不到才去基类中找)。
两个类之间有哪些可能的关系?
-
is-a关系:继承 —> 从一个类派生出另一个类
~ class student( Person)
~ a student is a person. -
has-a关系∶关联 —> 把一个类的对象作为另外一个类的对象的属性
~ a person has an identity card.
~a car has an engine
~ (普通)关联
~ 强关联:整体和部分的关联,聚合和合成 -
use-a关系∶依赖 —> 一个类的对象作为另外一个类的方法的参数或返回值
~a person use a vehicle
面向对象编程的四大支柱:
-
抽象 (abstraction):提取共性(定义类就是一个抽象过程,需要做数据抽象和行为抽象)
-
封装 (encapsulation):把数据和操作数据的函数从逻辑上组装成一个整体(对象)。
—> 隐藏实现细节,暴露简单的调用接口。
-
继承 (inheritance):扩展已有的类创建新类,实现对已有类的代码复用。
-
多态 (polymorphism):给不同的对象发出同样的消息,不同的对象执行了不同的行为。
—> 方法重写:子类对父类已有的方法,重新给出自己的实现版本。
练习:
工资(月薪)结算系统
-
三类员工:
- 部门经理:固定月薪,15000元
- 程序员:计时结算月薪,每小时200元
- 销售员:底薪+提成,底薪1800元,销售额5%提成
from abc import abstractmethod
class Employee:
"""员工"""
def __init__(self, no, name):
"""初始化方法
:param no: 工号
:param name: 名字
"""
self.no = no
self.name = name
@abstractmethod
def salary(self):
pass
class Manager(Employee):
"""部门经理"""
def salary(self):
"""工资(月薪)结算"""
return 15000
class Programmer(Employee):
"""程序员"""
def __init__(self, no, name):
super().__init__(no, name)
self.work_hours = 0
"""工作时长"""
def salary(self):
"""工资(月薪)结算"""
return self.work_hours * 200
class Salesman(Employee):
"""销售员"""
def __init__(self, no, name):
super().__init__(no, name)
self.sales = 0
"""销售额"""
def salary(self):
"""工资(月薪)结算"""
return self.sales * 0.05 + 1800
def main():
emps = [
Manager(1122, '刘备'), Programmer(2233, '诸葛亮'),
Salesman(3344, '关羽'), Salesman(4455, '张飞'),
Programmer(5566, '庞统'), Salesman(6677, '马超')
]
for emp in emps:
if type(emp) == Programmer:
emp.work_hours = int(input(f'请输入{emp.name}本月工作时长: '))
elif type(emp) == Salesman:
emp.sales = float(input(f'请输入{emp.name}本月销售额: '))
print(f'{emp.name}本月工资: {emp.salary()}元')
if __name__ == '__main__':
main()
子类对父类已有的方法,重新给出自己的实现版本,这个过程叫做方法重写(override)。
在重写方法的过程中,不同的子类可以对父类的同一个方法给出不同的实现版本,那么该方法在运行时就会表现出多态行为