-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathPolymorphismExample.py
144 lines (108 loc) · 5.51 KB
/
PolymorphismExample.py
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# -*- coding: utf-8 -*-
'''
多态即同一个行为具有多个不同表现形式或形态的能力。
表现形式为,子类重写父类方法,实现类实现接口方法,子类重写抽象类方法等。
多态性是指同一个方法调用可以根据对象的实际类型而有不同的行为。
当使用父类的引用变量来声明子类对象时,调用方法时将根据子类的类型而变化,这就是多态性。
多态三个必要条件:继承、重写、父类引用指向子类对象。
方法重写:重写是通过子类提供的方法来覆盖父类中的方法。子类可以提供不同的方法实现,但方法名与父类中的方法一致。
动态绑定:对于方法重写,方法的选择是在运行时(动态)绑定的而不是编译时(静态)确定的。编译器不知道对象的实际类型,只有在运行时才能够确定。
本示例:
- 多态性的应用:
使用一个Animal类型的数组来存储不同类型的动物对象,包括Dog、Cat和Pig。
在遍历数组时,调用Animal类的eat()方法。根据多态的特性,实际上调用的是各子类的eat()方法,展示了不同对象的不同行为。
- 方法重载的应用:
在Animal类中,我们定义了两个版本的eat()方法,它们具有相同的名称但不同的参数列表。
在调用eat()方法时可以选择不同的参数,从而实现不同的行为。例如,我们可以调用animal.eat("some food"),这会调用重载形式的eat()方法。
- 方法重写的应用:
在Dog、Cat和Pig类中,我们重写了Animal类的eat()方法,以提供各自特定的行为。
这允许我们根据对象的实际类型来调用适当的方法,而不是始终调用基类的方法。例如,即使数组中存储的是Dog对象,但在遍历时实际上调用的是Dog类重写后的eat()方法。
- 好处:
- 灵活性和可扩展性:我们可以轻松地向程序中添加新的动物类型,而不需要修改现有的代码。只需创建新的派生类并重写父类的方法即可。
- 代码重用:通过将对象视为其超类型,我们可以在程序中重用相同的代码。例如,在遍历数组时,我们使用了相同的方式处理不同类型的动物对象。
- 简化代码:多态性、方法重载和方法重写使得我们的代码更加简洁和清晰,因为我们不需要针对每种情况编写单独的代码,而是可以通过统一的方式处理不同的对象和行为。
'''
# Python在面向对象上与Java、C#等也有不同,实例化对象无需通过引用类型来声明对象,也就没有父类引用指向子类对象的概念。
# 使用时不受类型严格限制,因此更加灵活。在这一点上Python与JS更为接近。
# 多态的核心概念是:同一个行为作用于不同的对象上时,可以产生不同的解释和不同的执行结果。
# 定义动物基类
class Animal:
def __init__(self):
self.name = "Animal"
# 方法重写:同名方法
def eat(self):
print("Animal is eating...")
# 方法重载:python不支持,故另起名字
def eat_food(self, food):
print(f"Animal is eating {food}...")
def get_name(self):
return self.name
# 定义狗类,继承自动物基类
class Dog(Animal):
def __init__(self):
# 执行父类方法
super().__init__()
self.name = "Dog"
# 方法重写:子类重写父类的方法
def eat(self):
print("Dog is eating...")
# 方法重写:子类重写父类的方法
def eat_food(self, food):
print(f"Dog is eating {food}...")
# 子类自有方法
def bark(self):
print("Dog is barking...")
# 定义猫类,继承自动物基类
class Cat(Animal):
def __init__(self):
super().__init__()
self.name = "Cat"
# 方法重写:子类重写父类的方法
def eat(self):
print("Cat is eating...")
# 方法重写:子类重写父类的方法
def eat_food(self, food):
print(f"Cat is eating {food}...")
# 子类自有方法
def meow(self):
print("Cat is meowing...")
# 定义猪类,继承自动物基类
class Pig(Animal):
# 方法重写:子类重写父类的方法
def eat(self):
print("Pig is eating...")
# 方法重写:子类重写父类的方法
def eat_food(self, food):
print(f"Pig is eating {food}...")
# 子类自有方法
def oink(self):
print("Pig is oinking...")
# 测试验证
dog = Dog()
cat = Cat()
pig = Pig()
# 创建动物数组,无需转型,都是列表成员
animals = [dog, cat, pig, Animal()]
# 遍历动物数组,调用各自的方法
for animal in animals:
print("name:", animal.get_name())
# 调用对象的eat方法
animal.eat()
# 调用对象的eat方法的重载形式
animal.eat_food("some food")
# 类型判断,无需类型转换,直接调用子类的私有方法
if isinstance(animal, Dog):
animal.bark() # 调用Dog类的bark方法
elif isinstance(animal, Cat):
animal.meow() # 调用Cat类的meow方法
elif isinstance(animal, Pig):
animal.oink() # 调用Pig类的oink方法
dogPtr = Dog()
catPtr = Cat()
pigPtr = Pig()
dogPtr.eat() # 调用Dog类的eat方法
dogPtr.bark() # 类型强制转换并调用Dog类的bark自有方法
catPtr.eat() # 调用Cat类的eat方法
catPtr.meow() # 类型强制转换并调用Cat类的meow自有方法
pigPtr.eat() # 调用Pig类的eat方法
pigPtr.oink() # 类型强制转换并调用Pig类的oink自有方法