实例看多态
近来看了一下多态性,把我的一些感受以例子的形式记录一下。
一.形象理解
两条理解的原则:
(1
//c++ code
BaseClass *p;
DerivedClass obj;
p = &obj;
//C# code
BaseClass obj = new DerivedClass();
(2
Shape是基类,
// Java Code
static void func(Shape s)
{
s.Draw();
}
如果发生了这样的调用:
Line l = new Line();
Circle c = new Circle();
func(l);
func( c);
一个Circle
通过这两条原则我们可以理解上面的多态。正是由于多态,使得我们不必要这样去做:
IF 你是一个
ELSE IF 你是一个
ELSE …
我们只要给这个被声明成为Shape
二.一切皆因虚函数
先看看实现多态的基本条件:
(1) 基类含有虚函数
(2) 继承类把这个虚函数重新实现了
(3) 继承类也可能没有重新实现基类的所有虚函数,因此对于这些没有被重新实现的虚函数不能发生多态。
再看一下几种语言里一些特别的规定:
1. C++
(1
(2
(3
(4
2. Java
(1
(2
//Java Code
class BaseClass
{
public void hello(){};
}
class DerivedClass extends BaseClass
{
public void hello()
{
System.out.println(“Helloworld!”);
}
public static void main(Stringargs[])
{
BaseClass obj = newDerivedClass();
obj.hello();
}
}
输入是Helloworld!。这样就实现了多态。
(3
//Java Code
public abstract AbstractClass
{
public abstract void hello();
//…
}
3. C#
C#对于多态的编写是最为严格和严谨的。
(1
(2
(3
//C# Code
public class BaseClass
{
public void hello()
{
System.Console.WriteLine(“Hello,this come from BaseClass”);
}
}
public class DerivedClass : BaseClass
{
public new void hello()
{
System.Console.WriteLine(“Hello,this is come from DerivedClass”);
}
public static void Main()
{
BaseClass obj = newDerivedClass();
obj.hello();
}
}
输出为Hello,thiscome from BaseClass,也就是说这并没有实现多态(非多态)。
(4
当派生类重新实现基类的虚函数(或纯虚函数)时,必须用
//C# Code
public abstract class AbsBaseClass
{
public abstract void hello();
}
public class DerivedClass : AbsBaseClass
{
public void hello()
{
System.Console.WriteLine(“Hello world!”);
}
public static voidSayHello(AbsBaseClass obj)
{
obj.hello();
}
public static void Main()
{
DerivedClass _obj =new DerivedClass();
DerivedClass.SayHello(_obj);
}
}
输出为Helloworld!
三.多态的反溯
继承类对象在发生多态时,并是不完全抛开基类不管的,它会去查看基类的虚函数列表,在这个列表的范围内才会发生多态。
让我们来看一个比较复杂的例子:
// Java Code
class A
{
protectedvoid hello(Object o)
{
System.out.println("A- Object");
}
}
class B extends A
{
protectedvoid hello(String s)
{
System.out.println("B- String");
}
protectedvoid hello(Object o)
{
System.out.println("B- Object");
}
};
class C
{
publicstatic void main(String args[])
{
Objectobj = new Object();
Stringstr = "ABC";
Aa = new B();
a.hello(obj);
a.hello(str);
}
};
输出结果为:
B – Object
B – Object
正如上面所说的,由于基类里没有参数类型为
四.接口——仅仅是更抽象的抽象类
// Java Code
interface IBase
{
voidhello();
}
class DerivedClass implements IBase
{
publicvoid hello()
{
System.out.println(“Helloworld!”);
}
publicstatic void main(String args[])
{
IBaseobj = new DerivedClass();
obj.hello();
}
}
在Java
这里有一个小小的问题:如果IBase1
interface IBase1
{
voidhello();
}
interface IBase2
{
voidhello();
}
public class DerivedClass1 : IBase1,IBase2
{
publicvoid hello()
{
System.Console.WriteLine(“Helloworld!”);
}
}
public class DerivedClass2 : IBase1,IBase2
{
voidIBase1.hello()
{
System.Console.WriteLine(“Thiscome from IBase
}
voidIBase2.hello()
{
System.Console.WriteLine(“Thiscome from IBase
}
publicstatic void Main()
{
IBase1obj_1 = new DerivedClass1();
IBase2obj_2 = new DerivedClass1();
IBase1obj_3 = new DerivedClass2();
IBase2obj_4 = new DerivedClass2();
obj_1.hello();
obj_2.hello();
obj_3.hello();
obj_4.hello();
}
}
输出为:
Hello world!
Hello world!;
This come from IBase1
This come from IBase2
有两点注意:(1
加入这样的代码
DerivedClass2 t = new DerivedClass2();
t.hello();
编译错误:test.cs(44,3):error CS0117: “DerivedClass2
那就是说这个方法是属于接口的,但是接口不能含有具体的实现代码,这里是不是存在一定的矛盾呢?
欢迎与我交流:tanrui@sjtu.edu.cn
