各种语言中的多态

来源:互联网 发布:js弹出输入框 编辑:程序博客网 时间:2024/06/03 23:42

多态确切的含义是:同一类的对象收到相同的消息时,会得到不同的结果。而这个消息是不可预测的。多态,顾名思义,就是多种形态,也就是多种结果。

以Java为例,由于Java是强类型语言,因此变量和函数返回值是有状态的。比如实现一个add函数的功能,其参数可能是两个int型整数,也可能是两个float型浮点数,而返回值可能是整形或者浮点型。在这种情况下,add函数是有状态的,它有多种可能的运行结果。在实际使用时,编译器会自动匹配合适的那个函数。这属于函数重载的概念,需要说明的是,重载并不是面向对象里的东西,和多态也不是一个概念,它属于多态的一种表现形式。

多态性是一种通过多种状态或阶段描述相同对象的编程方式。它的真正意义在于:实际开发中,只要关心一个接口或基类的编程,而不必关心一个对象所属于的具体类。

很多地方会看到“PHP没有多态” 这种说法。实际上,不是它没有,而是它本来就是多态的。PHP作为一门脚本语言,自身就是多态的,所以在语言这个级别上,不谈PHP的多态。在PHP官方手册也找不到对多态的详细描述。

既然说PHP没有多态这个概念(实际上是不需要多态这个概念),那为什么又要讲多态呢?可以看下面例子</>:

<?phpclass employee{    protected function working()    {        echo '本方法需要重载才能运行';    }}class teacher extends employee{    public function working()    {        echo '教书';    }}class coder extends employee{    public function working()    {        echo '敲代码';    }}function doprint($obj){    if(get_class($obj) == 'employee')    {        echo 'Error';    }    else    {        $obj->working();    }}doprint(new teacher());doprint(new coder());doprint(new employee);

通过判断传入的对象所属类不同来调用其同名方法,得到不同结果,这是多态吗?如果站在C++角度,这不是多态,这只是不同类对象的不同表现而已。C++里的多态指运行时对象的具体化,指同一类对象调用相同的方法而返回不同的结果。看个C++例子,如下:

#include <cstdlib>#include <iostream>using namespace std;class father{public:father():age(30){cout<<"父类构造法,年龄"<<age<<"\n";}-father(){cout<<"父类解析"<<"\n";}void eat(){cout<<"父类吃饭吃三斤"<<"\n";}virtual void run(){cout<<"父类跑1000米"<<"\n";} //虚函数protected:int age;};class son:public father{public:son(){cout<<"子类构造法"<<"\n";}~son(){cout<<"子类析构"<<"\n";}void eat(){cout<<"儿子吃饭吃一斤"<<"\n";}void run(){cout<<"儿子跑100米"<<"\n";}void cry(){cout<<"哭泣"<<"\n";}};int main(int argc, char*argv[]){    father *pf = new son;    pf->eat();    pf->run();    delete pf;    system("PAUSE");    return EXIT_SUCCESS;}

上面的代码首先定义一个父类,然后定义了一个子类,这个子类继承父类的一些方法并且有自己的方法。通过father * pf = new son; 语句创建一个派生类(子类)对象,并且把该派生类对象赋给基类(父类)指针,然后用该指针访问父类中的eat和run方法。

由于父类中的run方法加了virtual关键字,表示该函数有多种形态,可能被多个对象所拥有。也就是说,多个对象在调用同一名字的函数时会产生不同的效果。

这个例子和PHP的例子有什么不同呢?C++的这个例子所创建的对象时一个指向父类的子对象,还可以创建更多派生类对象,然后上转型为父类对象。这些对象,都是同一类对象,但是在运行时,却都能调用到派生类同名函数。而PHP中的例子则是不同类的对象调用。

由于PHP是弱类型的,并且也没有对象转换机制,所以不能像C++或者Java那样实现 father $pf = new son; 把派生类对象赋给基类的对象。然后在调用函数时动态改变其指向。在PHP的例子中,对象都是确定的,是不同类的对象。随意,从这个角度讲,这还不是真正的多态。

上面的代码通过判断对象的属性实现“多态”,此外还可以通过接口实现多态,代码如下所示:

<?phpinterface employee{    public function working();}class teacher implements employee{    public function working()    {        echo '教书';    }}class coder implements employee{    public function working()    {        echo '敲代码';    }}function doprint(employee $someone){    $someone->working();}doprint(new teacher());doprint(new coder());

这是多态吗?这段代码和上面的代码相比没有多少区别,不过这段代码中doprint函数的参数是一个接口类型的变量,符合“同一类型,不同结果”这一条件,具有多态的一般特征。因此,这是多态。

如果把文章开头的代码中的doprint函数的obj参数看做一种类型(把所有弱类型看做一种类型),那就可以认为该代码也是一种多态。

再次把三段代码放在一起品味,可以看出:区别是否多态的关键在于看对象是否属于同一类型。如果吧他们看做同一类型,调用相同的函数,返回了不同的结果,那么它就是多态;否则,不能称其为多态。由此可见,弱类型语言实现起来多态会更简单, 更灵活。

这篇文章主要解释了什么是多态,什么不是多态的问题。至于多态是怎么实现的,各种语言的策略是不一样的。但是,最终的实现无非就是查表和判断。总结如下:

  • 多态指同一类对象在运行时的具体化。
  • PHP语言是弱类型的,实现多态更简单,更灵活。
  • 类型转换不是多态。
  • PHP中父类和子类看做“继父”和“继子”关系,他们存在继承关系,但不存在血缘关系。因此子类无法向上转型为父类,从而失去多态最典型的特征。
  • 多态的本质就是if···else,只不过实现的层级不同。

0 0
原创粉丝点击