python进阶——类(三)方法重写、多态
本文最后更新于:1 年前
¶(五)方法重写
¶1. 概念
继承是对基类的完全继承,但是很多时候基类的方法并不能完全适用于派生类,此时需要对派生类继承的方法进行重写(override)。
方法重写是在派生类中定义一个和基类的同名方法,方法内部的代码块被重新实现,重写后的运行只会运行重写完成的方法,而不会调用基类的同名方法。
¶2. 分类:
方法重写包括覆盖和扩展两种方法。
¶(1)覆盖基类方法:
当基类的方法实现与派生类的方法实现完全不同时,可以通过覆盖直接重新编写。
重写实际上就相当于派生类正常实现方法,只是该方法会导致继承而来的方法不再能够被调用。
简单的例子如下:
1 |
|
对于__init__方法,派生类在不重写的情况下自动继承(继承顺序按上一篇博客决定),重写后也会发生覆盖,所以要注意此时的调用会无法访问基类__init__方法定义的属性。
¶(2)扩展:
当派生类除了自身功能外,还需要基类的方法提供的功能,也就是派生类的方法实现包含基类的方法实现,可以通过扩展完成重写。
扩展实际上就是覆盖,但是扩展在重写时使用super().基类方法完成调用基类方法,以此方式使基类方法成为了派生类方法的一部分。
也可以使用父类名.方法(self)完成调用基类方法,但不推荐使用。
简单的例子如下:
1 |
|
¶(六)多态
¶1. 概念:
多态包括多态和多态性。
多态是指一类事物具有多种形态,可以用单个类型的实体来表示不同场景中的不同类型——其对应的表现为不同的对象调用同一个接口,表示出了不同的状态。
多态性是指不同功能的函数可以使用相同的函数名,也就是用一个函数名调用不同功能的函数。
最直接的表现就是定义一个函数传入对象,通过方法名调用对象的某个方法,这样就可以根据不同对象调用不同方法了。
多态是在继承的基础上讨论的,多态必须发生在基类和派生类之间;多态要求必须发生方法重写——当然,即使对象所属的类之间没有继承关系也可以使用多态(不过多数时候这样的行为没有意义)。
多态只关心对象的实例方法是否同名,不关心对象所属类型。
多态实质就是:一个接口,多种实现。
¶2. 优点:
-
增加了程序的灵活性,增加了代码外部调用的灵活度,使其的通用性比较强。
-
增加了程序的可扩展性,可以为已有接口建立新的实现。
-
多态是调用的技巧,不会影响类的内部设计。
¶3. 应用:
-
对象所属的类之间没有继承关系,可以使用多态:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21class dog:
def who(self):
print("I am dog")
class cat:
def who(self):
print("I am cat")
class bird:
def who(self):
print("I am bird")
def funwho(object):
object.who()
d=dog()
c=cat()
b=bird()
funwho(d)
funwho(c)
funwho(b)
# 运行结果:
# I am dog
# I am cat
# I am bird用funwho函数调用传入对象的who方法,通过不同对象表现出了不同结果。
扩展时不需要修改已有的内容,只需要定义新类和新方法,然后直接调用即可,便于扩展。
-
有继承关系,可以使用,应用更广泛:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33class animal:
def who(self):
print("I am an animal")
class dog(animal):
def who(self):
super().who()
print("I am dog")
class cat(animal):
def who(self):
super().who()
print("I am cat")
class bird(animal):
def who(self):
super().who()
print("I am bird")
def funwho(object):
object.who()
a=animal()
d=dog()
c=cat()
b=bird()
funwho(a)
funwho(d)
funwho(c)
funwho(b)
# 运行结果:
# I am an animal
# I am an animal
# I am dog
# I am an animal
# I am cat
# I am an animal
# I am bird
¶4. 鸭子类型:
实际上,python的多态并不是显式支持的,其多态更像是python强大功能的体现之一,python对于动态类型的使用更多的是鸭子类型(Duck Typing)。
鸭子类型是程序设计中动态类型的一种风格,在这种风格中,一个对象的有效语义,不是由继承自特定类或者实现特定接口决定,而是由当前方法和属性的集合决定。
鸭子类型实际上可以由James Whitcomb Riley的鸭子测试来表述:
“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”
鸭子类型中,关注的不是对象类型本身,而是对象的用法。
鸭子类型的表现形式就是上面所谓“多态”的表现形式,函数不会检查对象的类型,而是只关注其是否有相关的方法,有的话即可正确调用。
比起多态,鸭子类型更符合Python的"一切接对象"的设计理念。