Hongbo

Oct 17, 2023

关于多态(2)

前提继承(实现)、覆盖(override)、向上转型

目的:通过允许向上转型,实现动态绑定,在”不变“中实现“变化”。

原则:开闭原则。

实现:使用基类的引用或者指针,引用或者指向子类对象。这些不同的子类实现了一些基类中相同的方法,但各有自己的不同操作,在进行这些相同操作时,系统会根据实际引用和指向的对象,确定需要调用哪一个子类对象的那一个共同方法。

影响:实现了静态语言的动态绑定,解决参数传递只能传递指定类型的局限性,有利于实现开闭原则。

注意:在向上转型后,该引用不能调用子类对象独有的方法。解决方法:强制类型转换,不安全。

技术:虚函数指针,虚函数表,虚函数切片。

示例:C++,Java,Python的多态实现,Java的interface与abstract类的区别。

  • C++
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
//C++(1)
/*
定义一个函数为虚函数,不代表函数为不被实现的函数。
定义它为虚函数是为了允许用基类的指针来调用子类的这个函数。
定义一个函数为纯虚函数,才代表函数没有被实现。
定义纯虚函数是为了实现一个接口,起到一个规范的作用,规范继承这个类的程序员必须实现这个函数。
*/
#include<iostream>

//c++中需要虚函数,才能实现多态(虚函数表),普通方法的重写不能实现多态
//包含虚函数的类并实现(低度抽象),可以实例化
class People
{
public:
virtual void speak(){
std::cout << "People speak!" << std::endl;
};
};

class Man: public People{
public:
void speak(){
std::cout << "Man speak!" << std::endl;
};
};

class Woman: public People{
public:
void speak(){
std::cout << "Woman speak!" << std::endl;
}
};

void Func(People* people){
people->speak();
}
//测试
int main(){
//有虚函数但实现,可以实例化
People pp;
pp.speak();

//使用基类指针指向子类,实现多态
Man* man=new Man();
People* p =man;
Func(p);

Woman woman;
Func(&woman);
//输出:
//People speak!
//Man speak!
//Woman speak!

return 0;
}
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
//C++2
#include<iostream>
//只要类中包含纯虚函数,则该类为抽象类,不能实例化
//c++中需要虚函数,才能实现多态

//只有纯虚函数的类,(高度抽象)为抽象类,不能实例化,相当java的接口
//子类必须实现纯虚函数,否则子类也为抽象类
class Human1
{
public:
virtual void eat()=0;
virtual void sleep()=0;
};

//包含虚函数与纯虚函数的类,为抽象类(中度抽象),不能实例化,相当于java中的抽象类
//子类必须实现纯虚函数,否则子类也为抽象类
class Human2
{
public:
virtual void eat()=0;
virtual void speak(){
std::cout << "Human speak!" << std::endl;
}
};

int main(int argc, const char** argv) {

// Human1 human;
// Human2 human2;
//以上声明均会报错:variable type 'Human2' is an abstract class
//测试代码省略,同于Java
return 0;
}

  • python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#python
#python的多态不严谨,鸭子模型
class Creature:
def eat(self):
...

@staticmethod
def staticmethod():
...

class Human(Creature):
def eat(self):
print("Human eats something!")

class Animal(Creature):
def eat(self):
print("Animal eats something!")

#test
def Func(creature):
creature.eat()

Func(Human())
Func(Animal())
OLDER >