在本系列中,我們以CodeProject上比較火的OOP系列博客為主,進行OOP深入淺出展現(xiàn)。
成都創(chuàng)新互聯(lián)公司是網(wǎng)站建設(shè)技術(shù)企業(yè),為成都企業(yè)提供專業(yè)的成都做網(wǎng)站、成都網(wǎng)站制作、成都外貿(mào)網(wǎng)站建設(shè),網(wǎng)站設(shè)計,網(wǎng)站制作,網(wǎng)站改版等技術(shù)服務(wù)。擁有10年豐富建站經(jīng)驗和眾多成功案例,為您定制適合企業(yè)的網(wǎng)站。10年品質(zhì),值得信賴!
無論作為軟件設(shè)計的高手、或者菜鳥,對于架構(gòu)設(shè)計而言,均需要多次重構(gòu)、取舍,以有利于整個軟件項目的健康構(gòu)建,有些經(jīng)驗是前輩總結(jié)的,我們拿來使用即可,有些是團隊知識沉淀的,總之復用前人好的思想有利于減少返工。當然,在面試的時候,如果能圍繞OOP大談特談,自然會加分多多的。
開始閱讀本系列博客的預備知識,多態(tài)、封裝、面向?qū)ο缶幊痰龋埻ㄟ^MSDN學習。如下圖的術(shù)語,您應(yīng)該耳熟能詳?shù)?。本系列文章使用C#作為唯一腳本語言。
OOP代表的是面向?qū)ο缶幊蹋∣bject-Oriented Programming),它基于對象的整體進行編程,取代了基于過程函數(shù)的編程思想。具體實現(xiàn)是圍繞對象進行數(shù)據(jù)、函數(shù)封裝,而不是基于邏輯關(guān)系。OOP中的對象直達的是一個特定的類型、或者某類型的實例對象、更多時候是一個class。每個class對象的結(jié)構(gòu)基本相似,但是有各自特有的屬性和數(shù)據(jù)值。對象之間可通過對外的接口進行訪問:方法、屬性等。基于OOP的這些優(yōu)勢,獨立的對象可以修改而不會影響到其他對象,這樣會比較方便的升級軟件減少潛在的bug。軟件系統(tǒng)隨著時間的推移,會變得越來越大,OOP編程思想有效的提高了系統(tǒng)代碼的可讀性和管理性。
下面用5個術(shù)語來說明OOP的具體概念是什么:
數(shù)據(jù)抽象(Data Abstraction):數(shù)據(jù)抽象是對需要操作的物體進行建模的出發(fā)點,既對使用對象進行了抽象,隱藏了內(nèi)部的細節(jié)(對使用的最終用戶而言)。用戶可以非常方便的使用class的方法、數(shù)據(jù),而不用關(guān)心數(shù)據(jù)創(chuàng)建、運行邏輯的背后復雜的過程。我們以真實世界為例,當你騎一輛自行車的時候,不用考慮變速齒輪的原理如何驅(qū)動鏈條、車輪吧。
繼承(Inheritance):繼承是OOP概念中最流行的一個概念。繼承給程序員提供了可復用代碼的優(yōu)勢?;惗x好函數(shù)邏輯,子類通過繼承,可實現(xiàn)直接訪問--就想子類自身的方法一樣方便。
數(shù)據(jù)封裝(Data Encapsulation):對class的成員變量、成員函數(shù)通過訪問控制符進行包裝,則稱為數(shù)據(jù)封裝。訪問控制符有public、Protected、Private、Internal 4種類型。
多態(tài)(Polymorphism):對象可通過傳遞不同參數(shù)實現(xiàn)相同的動作,這種行為我們稱之為多態(tài)。我們以真實世界為例,“開車”這個方法,對不同類型的用戶要提供不同的參數(shù)實現(xiàn)多態(tài),如Car.Drive(Man), Car.Drive(Woman)等。
消息通信(Message Communication):消息通信意味著通過通過消息進行class函數(shù)的調(diào)用、執(zhí)行。
在本節(jié),我們分別用代碼片段來闡述各自類型的多態(tài)類型:函數(shù)重載、早期綁定、編譯器的多態(tài)。
先創(chuàng)建一個console 工程,并命名為InheritanceAndPolymorphism,然后添加類Overload.cs,再添加
DisplayOverload
函數(shù)。
public class Overload { public void DisplayOverload(int a){ System.Console.WriteLine("DisplayOverload " + a); } public void DisplayOverload(string a){ System.Console.WriteLine("DisplayOverload " + a); } public void DisplayOverload(string a, int b){ System.Console.WriteLine("DisplayOverload " + a + b); } }
在Program.cs添加如下代碼:
class Program { static void Main(string[] args) { Overload overload = new Overload(); overload.DisplayOverload(100); overload.DisplayOverload("method overloading"); overload.DisplayOverload("method overloading", 100); Console.ReadKey();
運行程序,結(jié)果如下:
DisplayOverload 100
DisplayOverload method overloading
DisplayOverload method overloading100
Overload類中的
DisplayOverload提供了3類不同的重載函數(shù):方法名相同,參數(shù)類型和個數(shù)不同。C#中的這種方式成為重載,既我們不需要為每類函數(shù)定義不同名字的函數(shù),僅需要改變函數(shù)參數(shù)類型和個數(shù)即可實現(xiàn),這個也成為函數(shù)簽名。
用不同的返回值可以否? 我們試試下面的代碼:
public void DisplayOverload() { }public int DisplayOverload(){ }
肯定的結(jié)果是,Visual Studio會給予如下的報錯信息:
Error: Type 'InheritanceAndPolymorphism.Overload' already defines a member called 'DisplayOverload' with the same parameter types
從上面的結(jié)果可知:返回值不作為多態(tài)函數(shù)簽名。
我們再運行如下的代碼:
static void DisplayOverload(int a) { }public void DisplayOverload(int a) { }public void DisplayOverload(string a){ }
結(jié)果依然是報錯:
Error: Type 'InheritanceAndPolymorphism.Overload' already defines a member called 'DisplayOverload' with the same parameter types
結(jié)論:static的可見函數(shù)修飾符不作為重載簽名。
運行下面的代碼,試試out、ref可否作為重載簽名。
private void DisplayOverload(int a) { }private void DisplayOverload(out int a) { a = 100; }private void DisplayOverload(ref int a) { }
結(jié)果是如下的報錯:
Error: Cannot define overloaded method 'DisplayOverload' because it differs from another method only on ref and out
結(jié)論:ref、out傳遞參數(shù)修飾符也不能作為重載簽名。
一個函數(shù)可包含如下4種類型的參數(shù)傳遞:
值傳遞 (pass by value)
引用傳遞 (Pass by reference)
作為output參數(shù) (As an output parameter)
使用參數(shù)數(shù)組 (Using parameter arrays)
我們運行如下代碼:
public void DisplayOverload(int a, string a) { } public void Display(int a) { string a; }
不出意外,獲得如下報錯信息:
Error1: The parameter name 'a' is a duplicate
Error2: A local variable named 'a' cannot be declared in this scope because it would give a different meaning to 'a', which is already used in a 'parent or current' scope to denote something else
在相同的作用域中,參數(shù)名稱必須是唯一的。
在Overload.cs文件中,添加如下代碼:
public class Overload { private string name = "Akhil"; public void Display() { Display2(ref name, ref name); System.Console.WriteLine(name); } private void Display2(ref string x, ref string y) { System.Console.WriteLine(name); x = "Akhil 1"; System.Console.WriteLine(name); y = "Akhil 2"; System.Console.WriteLine(name); name = "Akhil 3"; } }
class Program { static void Main(string[] args) { Overload overload = new Overload(); overload.Display(); Console.ReadKey(); } }
Akhil
Akhil 1
Akhil 2
Akhil3
結(jié)論:我們通過ref引用傳遞了name的內(nèi)存地址,故修改x、y的值相當于直接修改name的值,故結(jié)果運行如上。
下面這段代碼演示了params關(guān)鍵字的作用:
在Overload.cs文件添加如下代碼:
public class Overload { public void Display() { DisplayOverload(100, "Akhil", "Mittal", "OOP"); DisplayOverload(200, "Akhil"); DisplayOverload(300); } private void DisplayOverload(int a, params string[] parameterArray) { foreach (string str in parameterArray) Console.WriteLine(str + " " + a); } }
在Program.cs文件添加如下代碼:
class Program { static void Main(string[] args) { Overload overload = new Overload(); overload.Display(); Console.ReadKey(); } }
Akhil 100
Mittal 100
OOP 100
Akhil 200
C#提供了params動態(tài)參數(shù)數(shù)組機制,非常方便的在運行時動態(tài)傳遞不同數(shù)量的同類型參數(shù)。
注:params關(guān)鍵詞僅能作為函數(shù)的最后一個參數(shù)適用。
我們再試試params關(guān)鍵字的函數(shù)簽名和非params關(guān)鍵字函數(shù)簽名的優(yōu)先級順序:
public class Overload { public void Display() { DisplayOverload(200); DisplayOverload(200, 300); DisplayOverload(200, 300, 500, 600); } private void DisplayOverload(int x, int y) { Console.WriteLine("The two integers " + x + " " + y); } private void DisplayOverload(params int[] parameterArray) { Console.WriteLine("parameterArray"); } }
Program.cs文件添加如下代碼:
class Program { static void Main(string[] args) { Overload overload = new Overload(); overload.Display(); Console.ReadKey(); } }
運行結(jié)果如下:
parameterArray
The two integers 200 300
parameterArray
從運行結(jié)果看,C#非常巧妙的進行非params函數(shù)的精準匹配優(yōu)先,如1個int類型\3個int類型,則用params類型匹配;2個int類型,用明確定義的函數(shù)進行匹配。
在本節(jié)中,我們進行OOP系列的第一篇,主要說明了編譯器的多態(tài),它也稱為早期綁定或者方法重載。同時,我們也學習C#中威力強大的params關(guān)鍵字,并用它來實現(xiàn)多態(tài)。
本文要點歸納如下:
C#函數(shù)重載的簽名規(guī)則是用參數(shù)的類型和數(shù)量判斷,而不是函數(shù)的名字。
函數(shù)返回值不作為重載簽名。
修飾符不作為簽名的一部分,如static
同函數(shù)中,多個參數(shù)名稱要唯一
ref、out是引用傳遞,傳遞的是參數(shù)的內(nèi)存地址
params 作為參數(shù)關(guān)鍵詞,僅能用于函數(shù)的最后一個參數(shù)
原文地址:http://www.codeproject.com/Articles/771455/Diving-in-OOP-Day-Polymorphism-and-Inheritance-Ear