我学Delphi心得及笔记面向对象系列(多态)

多态

1什么是多态?

1.1概念

多态的概念众说纷纭,下面是几种代表性的说法:

This ability to manipulate more than one type with a pointer or a reference to a base classis spoken of as polymorphism (C++ Primer》第838)。即用基类的指针/引用来操作多种类(基类和其派生类)的对象的能力称之为多态。它是从语言实现的角度来考虑的。

polymorphism provides another dimension of separation of interface from implementation, to decouple what from how(Think in Java3rd edtion),即多态提供了另外一种分离接口和实现(即把“做什么”与“怎么做”分开)的一种尺度。它是从设计的角度考虑的。

The ability to use the same expression to denote different operations is refered to as Polymorphism”,(Object-Oriented Methods Principles & Practice3rd Edition,第16)。简单的说,多态就是“相同的表达式,不同的操作”,也可以说成“相同的命令,不同的操作”。这是从面向对象的语义的角度来看的。

三种说法分别从不同的角度来阐述了多态的实质。其中第三种说法尤为确切,下面着重分析第三种说法。

先解释这句话的含义:

相同的表达式—函数调用

不同的操作  —根据不同的对象就有不同的操作。

举个例子来说明,比如在公司中有各种职责不同的员工(程序员,业务员,文管等),他们“上班”时,做不同的事情(也可以看作是一种业务逻辑),我们把他们各自的工作都抽象为"上班",关系如下:

                      员工

                    /   |   \     ——继承关系

              程序员业务员文管

每天上班时间一到,相当于发了一条这样的命令:

  “员工们.开始上班”(同一条表达式)

每个员工接到这条命令(同样的命令)后,就“开始上班”,但是他们做的是各自的工作,程序员就开始“Coding”,业务员就开始“联系业务”,文管员就开始“整理文档”。即“相同的表达式(函数调用)(在运行期根据不同的对象来执行)不同的操作

下面我们来用Delphi实现这个实例

View Code
Type
Employee
=Class(Tobject)//员工基类
public
procedure Work;Virtual;abstract;//开始工作的过程
end;
Programmor
=Class(Employee)//程序员类--继承自员工类
public
procedure Work;override;//程序员的工作过程
end;
BusinessMan
=Class(Employee)//业务员类--继承自员工类
public
procedure Work;override;//业务员的工作过程
end;
DocManager
=Class(Employee)//文档管理员类-----继承自员工类
public
procedure Work;override;//文档管理员的工作过程
end;

procedure Programmor.Work;//程序员的具体工作过程实现
begin
Showmessage(
'程序开始Coding');
end;

procedure BusinessMan.Work;//业务员的具体工作过程实现
begin
Showmessage(
'业务员开始联系业务');
end;
procedure DocManager.Work;//文档管理员的具体工作过程实现
begin
Showmessage(
'文档管理员开始整理文档');
end;

//上班了,各位员工开始工作
procedure TForm1.btn2Click(Sender: TObject);
const
Num
=3;
var
emp:
arrayof Employee;
i:Integer;
begin
 
//实现多态
setLength(emp,Num);
emp[
0]:=Programmor.Create;
emp[
1]:=BusinessMan.Create;
emp[
2]:=DocManager.Create;
for i:=0to length(emp)-1do
emp[i].Work;
//分别调用各员工的具体的工作过程
end;

1.2多态的意义

封装和继承的意义是它们实现了代码重用,而多态的意义在于,它实现了接口重用(同一的表达式),接口重用带来的好处是程序更易于扩展,代码重用更加方便,更具有灵活性,也就能真实地反映现实世界。

比如为了更好地管理,把程序员分为C++程序员,Delphi程序员。…

                      员工

                    /   |   \      ——继承关系

              程序员业务员文管

               /   \               ——继承关系

      C++程序员  Delphi程序员

代码如下:


View Code
Type
CppProgarmmer
=class(Progarmmer)//c++程序员,继承自程序员类
public
procedure Work;override;//c++程序员的工作过程
end;
DelphiProgarmmer
=class(Progarmmer)//delphi程序员,继承自程序员类
public
procedure Work;override;//delphi程序员的工作过程
end;

procedure CppProgarmmer.Work;
begin
Showmessage(
'C++ 程序员开始高度Bug!');
end;
procedure DelphiProgarmmer.Work;
begin
Showmessage(
'Delphi 程序员开始Coding!');
end;
//现在重新调用
//上班了,各位员工开始工作
procedure TForm1.btn2Click(Sender: TObject);
const
Num
=5;
var
emp:
arrayof Employee;
i:Integer;
begin
 
//实现多态
setLength(emp,Num);
emp[
0]:=Programmor.Create;
emp[
1]:=BusinessMan.Create;
emp[
2]:=DocManager.Create;
emp[
3]:=CppProgarmmer.Create;
emp[
4]:=DelphiProgarmmer.Create;
for i:=0to length(emp)-1do
emp[i].Work;
//分别调用各员工的具体的工作过程
end;



多态的实质是:相同的表达式,不同的操作(就这么简单),

OOP语言的实现来讲,多态就是使用基类的指针/引用来操作(派生类)对象,在运行期根据实际的对象,来执行不同的操作方法;

或者换一种更形象的说法:由对象自己来决定自己操作方式,编译器只需下达做什么的命令(做什么what),而不要管怎么做(how),"怎么做"由为对象自己负责。

这样就实现了接口和实现的分离,使接口重用变得可能

其实多态也简单!那么使用多态应该注意什么呢?下面是一些建议:

分析业务逻辑,然后把相关的事物抽象为“对象”,再用对象方法封装业务逻辑。把一些具有多态性的操作,在基类中声明为虚方法(virtual Method)

对于在基类没有必要实现的就声明为抽象方法(virtual Abstract Method),然后在其派生类中再覆载它(Override),在使用的时候用基类的引用/指针来调用,

这样顺理成章地实现了现实世界中的多态性。记住千万不要为了多态,而去实现多态,这是一种走形式化的做法,是没有意义的。

由于基类与派生类有一种天然“耦合”关系,修改基类就会导致“牵一发而动全身”,这将是非常麻烦的事情!因此要尽量弱化基类的功能实现,

必要时把它设计为“抽象类”,并保证稳定的接口,这可以通过预留一些冗余的虚函数(或抽象函数)来实现

原文地址:https://www.cnblogs.com/youshan/p/2118700.html