依赖关系
当我们选择实例方法来执行某个功能时,如果需要使用另一个类的实例的方法来完成,则称这两个类之间存在关联关系。
示例:
class Person():
def play(self, tools):
tools.run()
print("很开心,能玩游戏了")
class Computer():
def run(self):
print("电脑开机,可以运行")
class Phone():
def run(self):
print("手机开机,可以运行")
c = Computer()
phone = Phone()
p = Person()
p.play(phone)
输出结果:
手机开机,可以运行
很开心,能玩游戏了
在示例中,定义了Person、Computer、Phone三个类,在Person类的play()方法中,可以使用Computer类或Phone类的实例作为参数。因为在Person类方法中实现时需要Phone类实例调用方法完成,所以这两个类之间存在依赖关系。
关联关系
一个类的属性类型是另外一个类的类型,则称这两个类之间存在关联关系。根据属性是单值或多值,关联关系又分为一对一关联、一对多关联等。
示例:一对一关联。
class Boy:
def __init__(self,name,girlFriend=None):
# 在初始化的时候可以给一个对象的属性设置成另一个类的对象
self.grilFriend = girlFriend # 一个男孩有一个女朋友
def meal(self):
if self.grilFriend:
print(f"带着他的女朋友{self.grilFriend}去吃饭")
else:
print("我单身,我快乐")
class Girl:
def __init__(self.name):
self.name = name
g = Girl("小红")
b = Boy("小明")
b.meal()
在示例中,表示的是一对一关联,Boy类中的属性girlFriend是Girl类的实例,这两个类之间存在一对一关联关系。
示例:一对多关联。
class School:
def __init__(self,name):
self.list = [] # 这里要装多个老师
self.name = name
def zhaopin(self,teach):
self.teach_list.append(teach)
def shangke(self):
for t in self.teach_list:
t.work()
class Teacher:
def __init__(self,name):
self.name = name
def work(self):
print(f"{self.name}在上课")
lnh = School("老男孩")
t1 = Teacher("张教授")
t2 = Teacher("李教授")
t3 = Teacher("王教授")
lnh.zhaopin(t1)
lnh.zhaopin(t2)
lnh.zhaopin(t3)
lnh.shangke()
示例中,表示的是一对多关联,School类中的属性teach_list是Teacher类的实例集合,这两个类之间存在一对多关联关系。
继承关系
类继承是在已有类基础上构建新类的机制,该新建类也成为子类。子类可以增加新的属性或功能,也可以继承父类的功能。继承所描述的是“is-a”的关系。通过继承机制,可以复用以前代码,大大提高开发效率。
在Python语言中使用继承机制时的注意事项:
1.子类拥有父类的属性和方法。
2.子类可以创建自己属性和方法。
3.子类可以对父类的方法进行覆盖实现。
4.子类可重新定义父类中的属性。
5.一个父类可由多个子类继承,一个子类也可继承多个父类。
6.如果父类定义了__init__()方法,子类也定义了自己的__init__()方法并且还要使用父类的__init__()方法, 子类需要显式调用父类的__init__()方法。如果子类需要扩展父类的初始化行为,可以添加__init__()方法参数。
7.当继承的多个父类中有相同的属性或方法时,会使用最后一个继承父类的属性或方法。
继承机制的出现,导致父类和子类相同行为出现的可能,以及在实际运行中的动态结果,此为多态。
多态(是从定义角度出发):同一类事物的多种形态,如猫的多种形态:白猫、黑猫、花猫等。
多态性(是从使用角度出发):同一种调用方式,不同的执行效果。具有不同功能的函数可以使用相同的函数名,这样就可以用一个函数名调用不同内容的函数。多态性依赖于继承机制,并且要定义统一的接口。
在程序语言中,多态实质就是定义了一个函数接口,在这个函数中定义了所有类中通用的功能。根据不同对象的相同调用接口,就得到不同的结果。
示例:多态
class Animal():
def run(self):
raise AttributeError("子类必须实现这个方法")
class Cat(Animal):
def run(self):
print("猫在跑")
class Pig(Animal):
def run(self):
print("猪在跑")
class Dog(Animal):
def run(self):
print("狗在跑")
a=Cat()
b=Pig()
c=Dog()
a.run()
b.run()
c.run()
输出结果:
猫在跑
猪在跑
狗在跑
但是这种写法存在着一种很严重的问题就是接口不统一。
示例:接口统一的写法。
def func(n):
n.run()
a = Cat()
b = Pig()
c = Dog()
func(a)
func(b)
func(c)
在示例中,演示了多态性定义和调用的两种方式。也体现了多态依赖的两个步骤。第一步,多态来自同一个父类的继承;第二步,为这些不同的子类定义相同的调用接口。
多态性的优势:
1.以不变应万变,增加了程序的灵活性。不论对象千变万化,调用方式都相同。
2.增加了程序的可扩展性。对于子类来说,使用者无需更改调用代码。