| 多态:在理解了封装和继承的同时,再让我们来看一看多态,如果要对多态进行形象、明了的阐述,将会花太多的篇幅,而现在关于多态的阐述又很多,您可以参考一些资料进行理解,此处仅仅进行简单的说明:多态是OOP中三个基本概念中最不好理解而且也是最有趣的部分,我们提到了封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类);它们的目的都是为了——代码重用。而多态则是为了实现另一个目的——接口重用!多态的本质就是将子类类型的指针赋值给父类类型的指针(在OP中是引用,实质上也是一种指针),只要这样的赋值发生了,多态也就产生了,因为实行了“向上映射”。
符加部分
{
也谈多态
封装、继承、多态构成了OOP的三大基本核心,封装、继承在之前我们曾作过介绍,而多态没有进行详细的介绍,在此给以补充,以完成OOP的三大主题来结束OOP的那一块。关于多态在很多资料上都有介绍,而且介绍的非常精彩,那么就让这篇文章再来进行一次总绍吧。
首先说点废话,以下的介绍以及实例中,我将以Object Pascal作为讲解的工具,而多态实质上是OOP的,不属于某一个工具的,它是一种信仰。在此处虽然以Objec Pascal来进行描述,其实可以扩展到任何的语言中。言归正转,继续我们的话题。
什么是多态?多态的本质是什么?多态和封装、继承有什么关系?它在OO中站有什么样的地位?多态给我们的工作代来了什么?本文就对这些问题加以阐述,在阐述的过程中来理解多态,认识多态,应用多态。
什么是多态?似乎没有一个统一的定义来规范多态,或许以我们自己的理解方式来解释多态更为贴切,在此我们不引用一些术语来进行定义,就初学者也可以理解的方式来形像这个定义:多态,顾名思议,就是多种形态,而这种多种形态又具体又体现在了什么地方?可以这样理解,我们可以用一种轮廓的物体来描述不至一种的多个物体,而至于我们到底要描述那个物体的状态,对于我而言不很重要。为什么要这样说呢?多态就是给我们体供了这样一种机制,我们对它仅仅是一个形式上的声明、定义,而具体的实现上的细节我们没有必要在此进行关心。或是具体的实现细节将交给别的东西去实现。我们所声明的这个基类从某种意义上而言只是一种定义。就如接口一样,没有实现部分,说到这儿,不得不说多态的本质了。多态的本质就是基类提供一系列的虚拟方法,如果试图去实现这个基类的话,将被编译器告之这样是行不通的。多态性的完整提体是交对象和他的子对象共同完成的一个思维方式。 多态性是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。对于用户而言,他们所关心的只不过是那些没有实现细节的父类所提供的虚拟方法罢了。如果以接口的话来讲就是:我们不去关心,也没有必要去关心接口的实现细节,我们所关心的仅仅是接口为我们提供的方法来完成我们的功能,而至于接口以何种方式来实现我们所需要的不同功能甚至是一个特定方式的多个功能都是其内部的事。不知道这样的解释是否让大家感觉很模糊,在理解上是否感觉不能很好的接受。请继续往下看。
谈到多态,我们首先要明白,对于多态而言,其父类提供了很多的虚拟方法,所以我们没有办法去直接实现这个父类,只能通过它的派生类去覆盖其提供的虚拟的方法,所以这就产生了多态。我们都知道,一个类可以被多个子类所继承,而每个子类所实现的方法又不一至,或是根据它们自己特有的特点对一个特定的方法的实现上因为类差别而存在着差别,但是我们完全可以通过父类去模糊化这些操作。对子类的方法的调用完全都可以通过基类去实现。由此而言,如果此基类没有被派生,那么这个类是完全没有存在的意义的!只有它被某一个子类派生了,那么它就正真的有存在的意义了。这种意义又提体在什么地方?或我们以什么手段来让这种意义成为焦点呢?这就是我们需要进一步走进多态的原因,如下所示:
TA = Class
Public
Procedure A ; virtual ; abstract;
Procedure B ; Virtual ; abstract;
Procedure C ; virtual ; abstract;
end;
当我们声明了类TA时,可以看到它有三个方法,而且也注意到了这三个方法都是完全虚拟的,如果此时我们试图实例化这个TA,将会没有任何的意义的,因为我们无法去实现类TA给我们提供的各种方法,或者说编译器将不提供空间/机制来让我们实现这些虚拟的方法。只有通过其子类进行覆盖这些虚拟方法才可以正真的将它们提体出它的作用。而覆盖就是说子类重新的定义、实现了基类的方法。如:
TB = Class(TA)
Private
B_Str : String;
Public
Constructor Create(Value : String);
Destructor Destroy();override;
{这是覆盖。设么地方可以用override?当他积累相对应的方法是虚拟的或是动态的时候才可以用override}
Procedure A ; override;
Procedure B ; override;
Procedure C ; override;
end;
TC = Class(TA)
Private
C_Str : String;
Public
Constructor Create(Value : String);
Destructor Destroy();override;
Procedure A ; override;
Procedure B ; override;
Procedure C ; override;
end;
这里有一个初学者或是不太注意语法的人经常混淆的概念。覆盖(override)和重载(overload)。上面说了,覆盖是指子类重新定义父类的虚函数的做法(inherted的用法是什么意思你真正的明白吗?)。而重载,是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)。如下:
Procedure OpenSQL(Sender : TADOQuery;SQLStr : String); overload;
{当重复时,返回为False,否则返回为True}
Function OpenSQL(SQLStr : String) : Boolean ; overload;
Function ifrepeat(TableName,FieldName,FieldValue : String;IntValue : Integer = 0):Boolean;overload;
Function ifRepeate(TableName : String;FieldName , FieldValue :
Array of String) : String ;overload;
上一页 [1] [2] [3] 下一页 |