Python中面向对象的多态

       本文从代码的重构谈了面向对象中的多态,及多态性的前提与好处。先记住这句话:多态的真正含义是:使用指向父类的指针或引用,能够调用子类的对象。

  • 先观察代码的重构

class Animal:
    def talk(self):
        print('makeNoise')  # 动物都能发出声音

    def eat(self):  # 动物会吃
        print('eat')

    def sleep(self):  # 动物会睡觉
        print('sleep')


class Dog(Animal):
    def talk(self):
        print('Dog...barking')  # 狗汪汪

    def eat(self):
        print('Dog eating bone')

    def sleep(self):
        print('Dog sleeping')


class Pig(Animal):
    def talk(self):
        print('Pig...hem')  # 猪哼哼

    def eat(self):
        print('Pig eating qingCai')

    def sleep(self):
        print('Pig sleeping')


def use_dog(dog):
    dog.talk()
    dog.eat()
    dog.sleep()


# 我要开始养狗了
# 第一只
p1 = Dog()
p1.talk()
p1.eat()
p1.sleep()
# 第二只
p2 = Dog()
p2.talk()
p2.eat()
p2.sleep()
# 开始养猪
# 第一只
p1 = Pig()
p1.talk()
p1.eat()
p1.sleep()
# 第二只
p2 = Pig()
p2.talk()
p2.eat()
p2.sleep()

 思考:狗养的越多,对象.方法() 调用越多

  • 观察红框中的代码,你不觉得很相似吗?仅对象名不一样,我们准备用方法(函数)改进

class Animal:
    def talk(self):
        print('makeNoise')  # 动物都能发出声音

    def eat(self):  # 动物会吃
        print('eat')

    def sleep(self):  # 动物会发声
        print('sleep')


class Dog(Animal):
    def talk(self):
        print('Dog...barking')  # 狗汪汪

    def eat(self):
        print('Dog eating bone')

    def sleep(self):
        print('Dog sleeping')


class Pig(Animal):
    def talk(self):
        print('Pig...hem')  # 猪哼哼

    def eat(self):
        print('Pig eating qingCai')

    def sleep(self):
        print('Pig sleeping')


'''
以下为改进代码
'''


# 用函数改进
def use_dog(dog):
    dog.talk()
    dog.eat()
    dog.sleep()


# 同样的对cat一样
def use_pig(pig):
    pig.talk()
    pig.eat()
    pig.sleep()


# 我要开始养狗了
# 第一只
d1 = Dog()
use_dog(d1)
# 第二只
d2 = Dog()
use_dog(d2)
# 开始养猪
# 第一只
p1 = Pig()
use_pig(p1)
# 第二只
p2 = Pig()
use_pig(p2)

  • 调用变的简洁

  •  仔细观察下图中红框中的代码,仅对象名不一样。

  •  再次重构

# 类的定义与上面的代码一样


'''
以下为改进代码
'''


def use_animal(animal):
    animal.talk()
    animal.eat()
    animal.sleep()


# 我要开始养狗了
# 第一只
d1 = Dog()
use_animal(d1)
# 第二只
d2 = Dog()
use_animal(d2)
# 开始养猪
# 第一只
p1 = Pig()
use_animal(p1)
# 第二只
p2 = Pig()
use_animal(p2)
  • 将每种动物的功能用use_animal统一起来。

从上面示例中可以看到,Dog、Pig是Animal的二个子类,在调用函数的时候,参数指定为Animal类型,但具体传入的是Anima的子类的对象Dog(d1, d2)、Pig(p1, p2)。

 当不同(Dog、Pig)去完成某个行为(talk、eat、sleep)时,会产生出不同的状态(狗有狗爱吃的骨头,猫有猫爱吃的青菜), 这就是多态。

多态性的前提:

  • 继承关系       例如: class Dog(Animal):
  • 方法重写        例如:def talk(self):  print('Dog...barking')  # 狗汪汪
  • 父类引用指向子类对象  例如:use_animal(p1), 实际上定义时参数animal 的类型应该为Animal 类型。

  • 假如我现在想养一只狐狸(Fox),  我仅需要添加Fox类的定义 ,然后调用use_animal(狐狸对象)
# 狐狸类定义
class Fox(Animal):
    def talk(self):
        print('Fox...whaaa')  # 狐狸哦哇

    def eat(self):
        print('Fox eating grape')

    def sleep(self):
        print('Fox sleeping')


'''
以下为改进代码
'''


def use_animal(animal):
    animal.talk()
    animal.eat()
    animal.sleep()



# 开始养狐狸
f1 = Fox()
use_animal(f1)
f2 = Fox()
use_animal(f2)

从上面代码的重过过程已偿到多态的好处:

  • 提高了代码的维护性
  • 提高了代码的扩展性

可以比较使用多态和不使用多态,很显然使用多态代码更清晰和简洁。除此之外,当我们增加新的子类(Fox、Cock)的时候无须变动代码就能适用,如果不使用多态,就需要添加use_fox,use_cock,use_xxx,...等方法。

猜你喜欢

转载自blog.csdn.net/chinagaobo/article/details/127419574