java/C#多态漫谈

最近面试深受打击,我感到自己的内功不足。于是翻看了一下《java编程思想》,对多态有了更深的认识。

以前只知道多态有什么用,怎么用,但是不知道多态的原理是什么,现在大概是知道了,我也不想私藏,现与大家分享,老鸟就不用看了。

多态实现的原理就是“方法调用后期绑定”。

什么叫后期绑定?

讲一个方法调用同一个方法主体关联起来被称作绑定。若在程序执行前进行绑定(例如编译的时候)的话,叫做前期绑定(c语言都是前期绑定)。相应的,在运行时候根据对象的类型进行绑定叫后期绑定,也叫动态绑定。也就是说,如果一个语言想实现后期绑定,就必须具有某种机制,以便能够在运行时能判断对象的类型,从而调用恰当的方法。也就是说,编译器一直不知道对象的类型,但是运行时方法调用机制能够找到正确的方法体,并加以调用。不管怎样,都必须在对象中安置某种类型信息。

在java中,除了static方法和final方法(private方法属于final方法)之外,其他的都默认进行后期绑定(就是可以多态)。如果将一个方法声明为final或者static或者private,就告诉编译器不需要对该方法动态绑定。这样,编译器就可以可以为final方法调用生成更有效的代码()。

总结一下:

1. java普通方法默认都是动态绑定的。

2. 父类static 和final方法(private除外),子类不可以重写,编译器会报错。其中构造器默认是static的。

3. 父类private(也默认final的)方法,子类可以声明同名方法(这个方法和父类同名方法只是名字相同,没有什么关系),但是不会多态,也不可能多态,因为父类方法为private的。

4. 子类需要多态的方法的可视范围(protected , public等)不能比父类的那个方法小(可以大),否则的话,父类可能没法找到子类的那个方法,会编译时报错。

5. java的各种属性不能多态。多态仅适用于方法。

下面看一个例子

1 class Base{
2
3 public int a=2;
4 public void fmethod(){
5 System.out.println(“base:fmethod”);
6 }
7 int getA(){
8 return a;
9 }
10 }
11
12 class Sub extends Base{
13 public int a=3;
14 public void fmethod(){ //final表示不尽兴多态
15 System.out.println(“sub:fmethod”);
16 }
17 //子类方法可视范围可以扩大
18 public int getA(){
19 return a;
20 }
21 }
22 public class Test {
23
24 public static void main (String args []) {
25 Base b=new Sub();
26 //方法多态,输出sub:fmethod
27 b.fmethod();
28 //属性不能多态,输出为2.
29 System.out.println(b.a);
30 //但是可以通过方法来实现属性的多态,输出3
31 System.out.println(b.getA());
32 }
33
34 }

C#和java的多态机制大部分是一样的,只是有一点,有着翻天覆地的不同。

不同:java普通方法默认是后期绑定的,而C#方法默认是前期绑定的,所以C#里面如果需要后期绑定(即多态),那么必须使用virtual + override+overide关键词对。另一方面,好像重写(这篇文章 所谓重写 ,表示需要多态的用override修饰的)的方法访问限制必须一致,不一致就报错,不清楚这个说法对不对。

闲话少数,上代码

1 class Base{
2
3 public int a=2;
4 public void fmethod(){
5 Console.WriteLine(base:fmethod);
6 }
7 //virtual关键词,可以提示编译器这个方法可以被后面的子类重写(子类方法需有override),
8 public virtual void gmethod()
9 {
10 Console.WriteLine(base:gmethod);
11 }
12
13 public virtual void hmethod()
14 {
15 Console.WriteLine(base:hmethod);
16 }
17 protected virtual int getA()
18 {
19 return a;
20 }
21 }
22
23 class Sub: Base
24 {
25 public int a=3;
26 //普通方法默认修饰符为new, public void fmethod = public new void fmethod
27 public void fmethod(){
28 Console.WriteLine(sub:fmethod);
29 }
30 //有override,与父类virtual 配对,多态
31 public override void gmethod()
32 {
33 Console.WriteLine(sub:gmethod);
34 }
35 //即使父类方法有virual,子类方法没有override,不会多态,
36 public void hmethod()
37 {
38 Console.WriteLine(sub:hmethod);
39 }
40
41
42 //子类重写的方法访问限制必须一致,对不对?
43 protected override int getA(){
44 return a;
45 }
46 }
47
48 class Subsub : Sub
49 {
50 //有override,与父类virtual 配对,多态
51 public override void gmethod()
52 {
53 Console.WriteLine(subsub:gmethod);
54 }
55 public static void Main(String[] args)
56 {
57 Base b = new Sub();
58 //输出base:fmethod
59 b.fmethod();
60 //输出sub:gmethod
61 b.gmethod();
62 //输出base:hmethod
63 b.hmethod();
64 //属性不能多态,输出为2.
65 Console.WriteLine(b.a);
66 Sub s = new Subsub();
67 //输出subsub:gmethod
68 s.gmethod();
69 }
70
71 }

转载请注明出处:博客园 stonehat http://www.cnblogs.com/stonehat/archive/2012/04/30/2476798.html

本文链接



You must enable javascript to see captcha here!

Copyright © All Rights Reserved · Green Hope Theme by Sivan & schiy · Proudly powered by WordPress

无觅相关文章插件,快速提升流量