python进阶——类(三)方法重写、多态

(五)方法重写

1. 概念

继承是对基类的完全继承,但是很多时候基类的方法并不能完全适用于派生类,此时需要对派生类继承的方法进行重写(override)。

方法重写是在派生类中定义一个和基类的同名方法,方法内部的代码块被重新实现,重写后的运行只会运行重写完成的方法,而不会调用基类的同名方法。

2. 分类:

方法重写包括覆盖和扩展两种方法。

(1)覆盖基类方法:

当基类的方法实现与派生类的方法实现完全不同时,可以通过覆盖直接重新编写。

重写实际上就相当于派生类正常实现方法,只是该方法会导致继承而来的方法不再能够被调用。

简单的例子如下:

1
2
3
4
5
6
7
8
9
10
11
class father:
def fun(self):
print("father")
class son(father):
def fun(self):
print("son")
s=son()
s.fun()
# 运行结果:
# son

对于__init__方法,派生类在不重写的情况下自动继承(继承顺序按上一篇博客决定),重写后也会发生覆盖,所以要注意此时的调用会无法访问基类__init__方法定义的属性。

(2)扩展:

当派生类除了自身功能外,还需要基类的方法提供的功能,也就是派生类的方法实现包含基类的方法实现,可以通过扩展完成重写。

扩展实际上就是覆盖,但是扩展在重写时使用super().基类方法完成调用基类方法,以此方式使基类方法成为了派生类方法的一部分。

也可以使用父类名.方法(self)完成调用基类方法,但不推荐使用。

简单的例子如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class father:
def fun(self):
print("father")
class son(father):
def fun(self):
super().fun()
print("son")
class son2(father):
def fun(self):
father.fun(self)
print("son2")
s=son()
s2=son2()
s.fun()
s2.fun()
# 运行结果:
# father
# son
# father
# son2

(六)多态

1. 概念:

多态包括多态和多态性。

多态是指一类事物具有多种形态,可以用单个类型的实体来表示不同场景中的不同类型——其对应的表现为不同的对象调用同一个接口,表示出了不同的状态。

多态性是指不同功能的函数可以使用相同的函数名,也就是用一个函数名调用不同功能的函数。

最直接的表现就是定义一个函数传入对象,通过方法名调用对象的某个方法,这样就可以根据不同对象调用不同方法了。

多态是在继承的基础上讨论的,多态必须发生在基类和派生类之间;多态要求必须发生方法重写——当然,即使对象所属的类之间没有继承关系也可以使用多态(不过多数时候这样的行为没有意义)。

多态只关心对象的实例方法是否同名,不关心对象所属类型。

多态实质就是:一个接口,多种实现

2. 优点:

  • 增加了程序的灵活性,增加了代码外部调用的灵活度,使其的通用性比较强。
  • 增加了程序的可扩展性,可以为已有接口建立新的实现。
  • 多态是调用的技巧,不会影响类的内部设计。

3. 应用:

  • 对象所属的类之间没有继承关系,可以使用多态:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    class 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
    33
    class 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的"一切接对象"的设计理念。


python进阶——类(三)方法重写、多态
http://example.com/2023/07/23/python进阶——类(三)方法重用、多态/
作者
07xiaohei
发布于
2023年7月23日
许可协议