动态多态的好处
案例描述:
分别利用普通写法和多态技术:设计实现两个操作数进行运算的计算器类
多态的有点:
- 代码组织结构清晰
- 可读性强
- 利于前期和后期的扩展以及维护
先来看一下普通实现写法:
#include<iostream>
using namespace std;
// 多态带来的好处:
// 分别利用普通写法和多态技术实现计算器。
class Calculator
{
public:
int getResult(string oper)
{
if (oper=="+")
{
return m_Num1 + m_Num2;
}
else if (oper=="-")
{
return m_Num1 - m_Num2;
}
else if (oper=="*")
{
return m_Num1 * m_Num2;
}
// else
// 如果想扩展新的功能,比如:平方,立方,开方等,需要修改源码。
// 在真实开发中 提倡 开闭 原则。
// 开闭原则:对扩展进行开放,对修改进行关闭。
// 因为修改的话:要整体大段代码查询,如果要扩展,只要继承重载就可以。
// 如果用多态,就方便多了。
}
int m_Num1;
int m_Num2;
};
void test01()
{
Calculator cal;
cal.m_Num1 = 10;
cal.m_Num2 = 20;
cout << cal.m_Num1 << " + " << cal.m_Num2 << " = " << cal.getResult("+") << endl;
cout << cal.m_Num1 << " - " << cal.m_Num2 << " = " << cal.getResult("-") << endl;
cout << cal.m_Num1 << " * " << cal.m_Num2 << " = " << cal.getResult("*") << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
在计算器类Calculator中getResult方法将类中两个成员相加。方法中有个string类型参数,输入不同的string符号,来实现多态控制。
但是这样有个问题:如果后续需要增加其他运算,比如平方,就需要修改源码,并且,修改完之后,要检查整体代码有没有问题。如此做法有违编程的开闭原则。
开闭原则:对扩展进行开放,对修改进行关闭。
在《C#学习笔记(二十二)抽象类与开闭原则:抽象类和接口怎么来的?》一文中:我们提到:
我们应该封装一些固定,不变的,稳定的、确定的成员;把不确定的,有可能改变的成员抽象为抽象成员、抽象类,留给子类去实现。
抽象类和开闭原则天生就是一对。
利用多态实现计算器
先声明一个抽象类,AbstractCalculator类中什么功能都不写。声明两个成员属性待用。把getResult函数抽象出来,写为虚函数,因为不知道后面具体如何实现,所以函数内部,只要写一个return 0即可。类似于C#中的接口类或者抽象类。
class AbstractCalculator
{
public:
virtual int getResult()
{
return 0;
}
int m_Num1;
int m_Num2;
};
然后,写一个加法/减法/乘法计算器的类。继承于抽象类AbstractCalculator。其中重写虚函数virtual可带可不带。
// 加法计算器类。
class AddCalculator :public AbstractCalculator
{
public:
int getResult()
{
return m_Num1 + m_Num2;
}
};
// 减法计算器类
class SubCalculator :public AbstractCalculator
{
public:
int getResult()
{
return m_Num1 - m_Num2;
}
};
class MultiCalculator :public AbstractCalculator
{
public:
int getResult()
{
return m_Num1 * m_Num2;
}
};
调用执行情况:
void test01()
{
// 多态的使用条件:
// 父类的指针或者引用,指向子类的对象。Animal animal = cat;
// 我们写一下:父类的指针指向子类对象。
AbstractCalculator* abc = new AddCalculator; // 发生多态。
abc->m_Num1 = 20;
abc->m_Num2 = 30;
cout << abc->m_Num1 << " + " << abc->m_Num2 << " = " << abc->getResult() << endl;
// 因为这个对象是new出来的,存在堆区,手动开辟创建,手动释放。
delete abc;
abc = new SubCalculator;
abc->m_Num1 = 30;
abc->m_Num2 = 20;
cout << abc->m_Num1 << " - " << abc->m_Num2 << " = " << abc->getResult() << endl;
delete abc;
abc = new MultiCalculator;
abc->m_Num1 = 30;
abc->m_Num2 = 20;
cout << abc->m_Num1 << " * " << abc->m_Num2 << " = " << abc->getResult() << endl;
delete abc;
}
代码量变大了。
多态带来的好处:
- 组织结构清晰。如果有一天发现:某个运算错了,比如加法。比如减法,马上可以定位到。而且只要修改这个类就行了,大型项目,列的越清晰越好。降低强耦合。
- 可读性强。一眼能看懂别人写的代码:并非你比别人强,而是写代码这个人厉害,让你一眼看懂。他也可以写成你看不懂的样子:那种样子叫做:恶心。
- 对于前期和后期的扩展以及维护性高。
增加新功能:是追加代码,而不是修改原来的代码。
这个案例是根据输入的运算符来操作运算。
C#中的多态案例实现:
C#中使用object作为参数来控制实现类型多态的。可以根据输入的两个对象类型,来选择不同运算。