熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

淺談.NET中不一樣的多態

2013-11-13 09:51:48  來源: .NET編程 

  在NET中多態通常意味著子類對於父類一種衍變子類繼承自父類擁有父類所定義的一切(public或protected)成員但同時它又可以修改(重寫或復寫)這些成員使其實現與父類以及其他子類完全不同我們可以說繼承體現了類的多態性

  大家應該很熟悉Duck的例子了吧?

  


    public abstract class Duck  
    {  
        public abstract void Quack();  
    }  
     
    public class MallardDuck : Duck  
    {  
        public override void Quack()  
        {  
            ConsoleWriteLine(Quack quack quack);  
        }  
    }  
     
    public class RubberDuck : Duck  
    {  
        public override void Quack()  
        {  
            ConsoleWriteLine(Squeak squeak squeak);  
        }  
    }  
     
    public class Program  
    {  
        public static void Main()  
        {  
            Duck duck = new MallardDuck();  
            duckQuack();  
            duck = new RubberDuck();  
            duckQuack();  
            ConsoleReadLine();  
        }  

  MallardDuck和RubberDuck雖然都繼承自抽象類Duck同樣擁有Quack()方法但它們卻有不同的實現產生不同的結果在聲明Duck類型時既可以實例化為Mallard也可以實例化為RubberDuck或者是其他繼承自Duck的類在運行時將自動調用各個子類的實現

  多態的這些特性使依賴注入和面向抽象編程成為可能其重要性不言而喻

  不一樣的多態
然而既然多態是指同一類事物之間的不同形態那麼我們為什麼要把對於多態的理解局限於類的繼承關系呢?在NET中是否還存在著非繼承關系的多態性呢?

  泛型體現了參數的多態性

  類型參數在泛型中通常解釋為占位符而我更願意將其理解為對參數的一種抽象以最常見的List為例List和List在語法上完全相同僅僅是類型參數有所不同然而它們卻是兩個完全不同的類也就是說是類型參數的不同導致了不同的類的形態

  


    public class MyList<T> 
    {  
        private T[] items;  
        private int size;  
        public void Add(T item)  
        {  
            if (size == itemsLength)  
            {  
                // modify capacity  
            }  
            items[size++] = item;  
        }  

  如果我們使用MyList在內部就會聲明一個字符串數組Add方法的參數也必須為string如果使用MyList在內部就會聲明一個int數組Add方法的參數也必須為int這看上去就像是T是string和int的基類在使用MyList時(相當於客戶端代碼)T既可以是string也可以是int或者是其他符合約束的類型但在設計時我們對這一切毫無所知

  您是否也覺得這是多態性的一種體現呢?

  再來看看十分經典的Swap的例子

  


    public class Swapper  
    {  
        private static void Swap<T>(ref T o ref T o)  
        {  
            T temp = o;  
            o = o;  
            o = temp;  
        }  

  Swap泛型方法就像是封裝了N個非泛型的Swap方法如Swap(ref int o ref int o)Swap(ref string o ref string o)等等在類型推斷特性的支持下您甚至可以像使用非泛型方法一樣來使用泛型方法參數T在某種程度上體現了不同的參數形態因此我們有理由認為泛型類型T體現了參數的多態性

  委托體現了方法的多態性

  委托是對擁有相同參數和返回值的所有方法的封裝只要方法擁有同樣的參數列表和返回值委托都認為它們屬於同一類型的方法可以添加到同一個委托鏈表中

  


    public delegate void FooDelegate(List<string> list string str);  
     
    public class DelegateTest  
    {  
        public void AddToList(List<string> list string strToAdd)  
        {  
            listAdd(strToAdd);  
        }  
     
        public static void PrintIfContains(List<string> list string strToCheck)  
        {  
            if (listContains(strToCheck))  
                ConsoleWriteLine(The list contains  + strToCheck);  
        }  
    }  
     
    public class Program  
    {  
        public static void Main()  
        {  
            List<string> list = new List<string>();  
            listAdd(Kirin);  
            DelegateTest delegateTest = new DelegateTest();  
            FooDelegate fooDelegate = new FooDelegate(delegateTestAddToList);  
            fooDelegate += new FooDelegate(DelegateTestPrintIfContains);  
            fooDelegate(list 麒麟NET);  
            ConsoleReadLine();  
        }  

  在上例中FooDelegate委托封裝了參數為List和string並且沒有返回值的方法任何符合上述約束的方法在FooDelegate中一視同仁AddToList實例方法與PrintIfContains靜態方法除了參數列表與返回值相同外

  內部實現完全不同但是它們卻可以添加到同一個委托鏈表中也就是說同一個委托可以定義並調用不同的方法(約束相同而實現不同)

  您是否也認為這是方法的多態性的一種體現呢?

  多態小結

  我們通常所討論的多態就是指子類對父類方法的重寫(虛方法)或覆蓋(非虛方法)這樣的理解未免過於狹隘NET強大的特性能夠實現其他語言中無法實現的多態性如本文所列舉的泛型和委托您是否認同筆者的觀點呢?如果認同您是否還能舉出其他的例子呢?

  您可能覺得本文缺乏技術含量的確是的本文並不包含多麼高深的技術和思想而只是筆者最近學習過程中一些瑣碎的領悟如果能夠幫助到您將是筆者的榮幸


From:http://tw.wingwit.com/Article/program/net/201311/11780.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.