多态性是面向对象的三大特性之一。当同一 *** 作用于不同的对象,可以有不同的解释,产生不同的执行结果,这种特性称为多态性。在计算机语言中的多态性,一般是指调用一个同名函数,参数不同,会产生不同的执行结果。多态性可以是静态的或动态的。静态多态性,是有若干同名函数,函数的形参类型和个数不同,系统在编译时,根据调用方法的实参类型及实参的个数决定调用哪个同名方法,实现何种 *** 作。动态多态性,是调用一个名字相同,形参的类型及个数完全一样的方法,在程序运行时根据实参的不同,完成不同的 *** 作。C#运行时的多态性通过虚方法实现,复杂难懂。python函数的形参没有类型,仅仅是一个名字,当形参被实参赋值,形参将引用(代表)实参,函数就可以 *** 作实参所引用的类对象,此概念将极大简化动态多态性的实现。由于python不用编译,是解释执行的,这里只讨论动态多态性。下面的例子说明用C#语言实现动态多态性的方法。
using System; class A { public void F() //非虚方法 { Console.Write(" A.F"); } public virtual void G() //虚方法 { Console.Write(" A.G"); } } class B:A //A类为B类的基类 { new public void F() //隐藏基类的同名非虚方法F(),注意使用new { Console.Write(" B.F"); } public override void G() //隐藏基类的同名虚方法G(),注意使用override { Console.Write(" B.G"); } } class Test { static void F2(A aA) //注意,参数为A类引用变量 { aA.G(); } static void Main() { B b=new B(); A a1=new A(); A a2=b; //允许基类引用变量引用派生类对象,a2引用A类派生类B的对象b a1.F(); //调用基类A的非虚方法F(),显示A.F a2.F(); //F()为非虚方法,调用基类A的F(),显示A.F b.F(); //F()为非虚方法,调用派生类B的F(),显示B.F a1.G(); //G()为虚方法,因a1引用基类A对象,调用基类A的G(),显示A.G a2.G(); //G()为虚方法,因a2引用派生类B对象,调用派生类B的G(),显示B.G F2(a2); //由于a2引用A类派生类B的对象b,调用派生类B的函数G(),显示B.G F2(a1); //实参为基类A对象,调用A类的函数G(),显示A.G } //最后两句调用一个名字相同,参数的类型及个数完全一样的方法F2,实参不同,完成不同的 *** 作 }
那么输出应该是:A.F A.F B.F A.G B.G B.G A.G
这里实现的要点是函数F2()的形参类型是类A,那么实参必须是A类对象或A类的派生类的对象,由于方法G()是虚方法,实参是A类对象,调用A类方法G(),实参是B类对象,调用B类方法G()。从而完成不同功能。这里涉及C#语言众多概念,十分复杂。
用Python实现相同功能,就简单多了,例子如下。
class A: def G(self): print(" A.G") class B(A): #class B(): #实际上,python并不要求B类是A类子类 def G(self): print(" B.G") def F2(o): o.G() aA=A() aB=B() F2(aA) F2(aB)
运行后,将显示:
A.G
B.G
实际上,实现动态多态性并不要求两个类存在继承关系,即上例并不要求B类是A类子类。如果B类定义中,第4条语句变为被注释的第5条语句,仍能正常工作,但要求两个类中被函数F2()调用的方法名称必须相同。
python多态性的实现是利用了变量是对类对象的引用(代表)的规则。这里解释这个规则,变量有两部分:字符组成的变量名和保存数据的内存单元地址,令a=2,其实是将整数2保存到内存数据区,在内存变量区先保存变量名a,在其后保存整数2所在内存的地址。因此必须对变量赋值,变量才可以使用。用变量访问数据,实际是通过变量名得到地址,用地址访问数据,这种方式被称作变量a引用(代表)了整数2。如果再令a=2.3,先将浮点数2.3保存到内存数据区,变量名保持不变,仅将其后的地址换为浮点数所在内存的地址,称作变量a引用(代表)了浮点数2.3,由于变量a不再引用整数2,如果也没有其它变量引用整数2,整数2所占用的内存单元将被垃圾收集器收回。函数F2()的形参仅仅有一个名字,还未保存对应数据的地址,应是None。当程序运行后,函数F2()将被调用,形参被实参赋值。实参一定是引用了某个类对象,那么形参也将和实参一样都引用了这个类对象,即两者都引用了同一个类对象,那么通过形参就可以调用这个类对象的函数,完成指定功能。
动态多态性概念在python中被广泛使用,很多内置函数都采用python动态多态性的概念。例如python内置函数len()能检测多种数据类型的长度,也是采用了动态多态性的概念,实现步骤和上例类似。python所有数据类型都是类,包括字符串类、列表类和元组类等,这些类中都应有一个同名的检测自己长度的方法,该方法返回值为所得到的长度,假如都为G()。内置函数len()实参必定引用(代表)某一个数据类对象,将实参赋值给形参,形参将也引用(代表)这一个数据类对象,通过形参可以调用这个数据类的方法G(),将得到该数据类对象的长度返回。如果对象是字符串,则返回字符数,如果对象是列表,则返回列表中的项目数等。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)