OOP之一:理解多态性(Polymorphism)和动态绑定(dynamic binding) (100分)

  • 主题发起人 majorsoft
  • 开始时间
M

majorsoft

Unregistered / Unconfirmed
GUEST, unregistred user!
多态性可以说是OOP(object-oriented programing)中最为显著的特性。
下面是我在学习C++中对"多态性"和"动态绑定"的理解。

一、多态性(Polymorphism)
定义是这样的,多态性指同一个操作作用在不同的对象上可以有不同的解释,并可以产生
不同的执行结果。 举一个例来理解它。先定义一个Tshape(图形)类,里面定义drew()"画
"这个方法(实际是这个方法的是用一个虚函数来实现的,在派生实际的类的时候,可以对
它进行重载),现在从这个Tshape类派生出Tcircle(圆)类和一个Tline类(直线),分别
创建一个对象circle和line,现在给这两个对象发同一操作"画",那么作用在circle上则"画"
圆,作用在line上则"画"直线,实际上它是这样实现的:通过把这个操作的消息发给不同的对
象时,每个对象将根据自己所属的类的draw()"画"的方法的定义去执行,从而产生不同的结果。
注意它并未这样表达:“如果你是一个Circle,就这样做;如果你是一个line,就那样做;
等等”。若那样编写代码,就需检查一个Shape所有可能的类型,如圆、直线等等。这显然是
非常麻烦的,而且每次添加了一种新的Shape类型后,都要相应地进行修改。实际上,我们只
需说:“你是一种几何形状,我知道你能将自己画,即draw();请自己采取那个行动,并自己
制所有的去控细节吧。”

二、动态绑定
与多态性密切相关的一个OOP特性就是"动态绑定(dynamic binding)",传统的编程语言把
函数(过程)调用放与目标代码的连接放在程序运行前进行(人们称之为"静态绑定"),而
动态绑定是把这个连接推迟到运行时才进行。就上个例子来说,在运行时,当发出消息(请
求对象draw()"画")时,circle圆和line直线分别根据将请求的操作和实现的方法(这个方
法在Tcircle和Tline分别有不同的定义)进行连接。
在C++和obeject pascal语言中,要求我们在定义方法时要用一个特殊的关键字来允许动
态绑定。在C++中,这个关键字是virtual
对面向对象的程序设计语言来说,它们用以实现多态性的方法叫作“动态绑定”。编译

和运行期系统会负责对所有细节的控制;

以上是我一些个人的看法。。欢迎大家交流看法。
转载:我的个人主页<a href=http://majorsoft.delphibbs.com>http://majorsoft.delphibbs.com</a>(E程序员论坛)
 
很多书上都有介绍,比这个详细多了
 
哪里有下载,请指点一下!
 
有人能贴出实现的代码吗?这一百分就给谁
最好是用C++
 
用delphi实现的代码要不要啊?C++的实现,那我得费心去写写的。

多态性的实际嘛!就是在基类中一定要有virtual(或dynamic)
的方法。然后在子类中,声明同样名称的方法,并加上override
关键字的。
具体实现它的时候,就是声明一个基类的变量,赋于它子类
的对象。以实现不同的行为!
个人感觉,要理解多态性,就要理解VMT,理解对象的结构,
知道对象的首位置的4个字节指向vmt,而vmt的首字节又指向
对象的首位置,理解静态方法,理解动态生成对象诸如等等!
 
oop pascal也可以啊!
有C++的就更好
 
真是对不起!这么多天,我在其它事情。
对于delphi多态性的例子,我也没有其它什么好的例子。
不过,简陋的例子,你可以看一下,请你不要动怒啦!

unit Unit2;
interface
USES windows, dialogs;
type tanimal=class
procedure doa;virtual;
end;
tdog=class(tanimal)
procedure doa;override;
end;

implementation

{ tnaimal }

procedure tanimal.doa;
begin
showmessage(self.ClassName );
end;
procedure tdog.doa;
begin
inherited

showmessage('a dog');
end;
end.
在另一个程序的验证程序中,写下如下代码:
。。。。。。。。(当然,要先写下uses unit2;)
var animal:tanimal;
begin
animal:=tanimal.create;
animal.doa;
animal.free;
animal:=tdog.Create
animal.doa
animal.Free
end;
父类声明了一个doa的虚拟方法,在子类中用声明一
个同名的加了override的方法,就过载了这个行为。
可以看到,声明了一个基于父类tanimal的对象变量,
但可以赋于它子类tdog的值,结果在doa上就表现出不
同的行为。这就是多态性。
在tdog的doa方法中,使用了inherited关键字,结果
就继承了tanimal的方法。如果不使用这个关键字,就
不会有showmessage(self.classname)的行为了。

如果把子类tdog的方法doa后的override关键字去掉,
使这个方法成为一个静态方法,那编绎器会发出警告:
Method'doa'hides virtual method of base type 'tanimal'
如果是这样声明:
var xxx:tdog;
begin
xxx:=tdog.create;
xxx.doa;
xxx.free;
end;
可以看到,doa的行为表现是tdog中的行为。
但如果是这样:
var xxx:tanimal
begin
xxx:=tdog.create;
xxx.doa;
xxx.free;
end;
可以发现,doa这个方法还是存在的。
 
多态的理解没太大问题,动态绑定的概念则偏差太多 :(
看看IDispatch的定义,再来考虑一下什么是动态绑定吧...
 
鄙人不是很同意“动态绑定”的说法,更严格地说,binding应该翻译成“联编”,
动态联编其实是将代码链接延迟到运行时进行,这种延迟主要通过填表
与查表(VMT)来完成,即将方法指针做为数据或操作的对象。
(虽然编译器的任务在编译结束就已经完成,但编译器确实已经在VMT中保留了项),

楼主的认识其实没有多少问题。笔者的新书《参透Delphi/Kylix》对此有详细的讨论。
 
to dedema,
十分感谢你的Pascal代码,请领分!
 
接受答案了.
 
顶部