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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM