多态

 什么是多态(Polymorphisn)?按字面的意思就是“多种形状”。引用Charlie Calverts对多态的描述——多态性是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作(摘自“Delphi4 编程技术内幕”)。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。多态性在Object Pascal和C++中都是通过虚函数(Virtual Function) 实现的。

  多态性是允许将父对象设置成为和一个和多个它的子对象相等的技术,比如Parent:=Child;   

  赋值之后,父对象就可以根据当前赋值给它的子对象的特性已不同的方式运作。也就是说,父亲的行为像儿子,而不是儿子的行为像父亲。   

  举个例子:从一个基类中派生,响应一个虚命令,产生不同的结果。   

  比如从某个积累继承出多个对象,其积累有一个虚方法Tdoit,然后其子类也有这个方法,但行为不同,然后这些子对象中的任何一个可以附给其基类的对象,这样其基类的对象就可以执行不同的操作了。实际上你是在通过其基类来访问其子对象的,你要做的就是一个赋值操作。

  使用继承性的结果就是可以创建一个类的家族,在认识这个类的家族时,就是把导出类的对象   当作基类的的对象,这种认识又叫作upcasting。这样认识的重要性在于:我们可以只针对基类写出一段程序,但它可以适   应于这个类的家族,因为编译器会自动就找出合适的对象来执行操作。这种现象又称为多态性。而实现   多态性的手段又叫称动态联编(dynamic binding)。   

简单的说,建立一个父类的变量,它的内容可以是这个父类的,也可以是它的子类的,当子类拥有和父类同样的函数,当使用这个变量调用这个函数的时候,定义这个变量的类,也就是父类,里的同名函数将被调用,当在父类里的这个函数前加virtual关键字,那么子类的同名函数将被调用

class A {
public:
A() {}

virtual void foo() {
cout << "This is A." << endl;
}
};

class B : public A {
public:
B() {}

void foo() {
cout << "This is B." << endl;
}
};

int main(int argc, char* argv[]) {

A *a = new B();
a->foo();

return 0;
}

这将显示:
This is B.

如果把virtual去掉,将显示:
This is A.   



========================================================================================
11.多态

面向对象的语言使用虚方法表达多态。这就意味着派生类可以有和父类具有同样签名的方法,并且父类可以调用派生类的方法【译注:此处应该是对象(或对象引用、指向对象的指针)】。在Java中,缺省情况下方法就是虚的。在C#中,必须使用virtual关键字才能使方法被父类调用。

在C#中,还需要override关键字以指明一个方法将重载(或实现一个抽象方法)其父类的方法。

Class B file://【译注:应为class B】

{

public virtual void foo () {}

}

Class D : B file://【译注:应为class D : B】

{

public override void foo () {}

}

试图重载一个非虚的方法将会导致一个编译时错误,除非对该方法加上“new”关键字,以指明该方法意欲隐藏父类的方法。

Class N : D file://【译注:应为class N : D】

{

public new void foo () {}

}

N n = new N ();

n.foo(); // 调用N的foo

((D)n).foo(); // 调用D的foo

((B)n).foo(); // 调用D的foo

和C++、Java相比,C#的override关键字使得阅读源代码时可以清晰地看出哪些方法是重载的。不过,使用虚方法有利有弊。第一个有利点是:避免使用虚方法轻微的提高了执行速度。第二点是可以清楚地知道哪些方法会被重载。

【译注:从“不过”至此,这几句话显然不合逻辑,但原文就是如此:

  “However, requiring the use of the virtual method has its pros and cons. The first pro is that is the slightly increased execution speed from avoiding virtual methods. The second pro is to make clear what methods are intended to be overridden.”。

  我认为,若将被我标为斜体的method改为keyword的话,逻辑上会顺畅些。这样,第一句话就可认为是和Java比,因其方法缺省是虚的,第二句话主要是和C++比】。然而,利也可能是弊。和Java中缺省忽略final修饰符

【译注:在Java中可利用final关键字,对方法上锁,相当于C#/C++中没有用virtual关键字修饰方法/成员函数的情况】以及C++中缺省忽略virtual修饰符相比,Java中缺省选项

【译注:即虚的】使得你程序略微损失一些效率,而在C++中,它可能妨碍了扩展性,虽然这对基类的实现者来说,是不可预料的。

posted on 2007-11-05 22:21  willlove  阅读(193)  评论(0)    收藏  举报

导航