![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI9s2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xCMy81dvRWYoNHLwEzX5xCMx8FesU2cfdGLwMzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5SNwQDOxczN5cTMyIDO1MDOyYzX2ATOwYTM3EzLcVDMyIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
無論作為軟體設計的高手、或者菜鳥,對于架構設計而言,均需要多次重構、取舍,以有利于整個軟體項目的健康建構,有些經驗是前輩總結的,我們拿來使用即可,有些是團隊知識沉澱的,總之複用前人好的思想有利于減少返工。當然,在面試的時候,如果能圍繞OOP大談特談,自然會加分多多的。
在本系列中,我們以CodeProject上比較火的OOP系列部落格為主,進行OOP深入淺出展現。
無論作為軟體設計的高手、或者菜鳥,對于架構設計而言,均需要多次重構、取舍,以有利于整個軟體項目的健康建構,有些經驗是前輩總結的,我們拿來使用即可,有些是團隊知識沉澱的,總之複用前人好的思想有利于減少返工。當然,在面試的時候,如果能圍繞OOP大談特談,自然會加分多多的。
開始閱讀本系列部落格的預備知識,多态、封裝、面向對象程式設計等,請通過MSDN學習。如下圖的術語,您應該耳熟能詳的。本系列文章使用C#作為唯一腳本語言。
OOP
1 是什麼OOP,以及OOP的優勢是什麼?
OOP代表的是面向對象程式設計(Object-Oriented Programming),它基于對象的整體進行程式設計,取代了基于過程函數的程式設計思想。具體實作是圍繞對象進行資料、函數封裝,而不是基于邏輯關系。OOP中的對象直達的是一個特定的類型、或者某類型的執行個體對象、更多時候是一個class。每個class對象的結構基本相似,但是有各自特有的屬性和資料值。對象之間可通過對外的接口進行通路:方法、屬性等。基于OOP的這些優勢,獨立的對象可以修改而不會影響到其他對象,這樣會比較友善的更新軟體減少潛在的bug。軟體系統随着時間的推移,會變得越來越大,OOP程式設計思想有效的提高了系統代碼的可讀性和管理性。
2 OOP的概念是什麼?
下面用5個術語來說明OOP的具體概念是什麼:
- 資料抽象(Data Abstraction):資料抽象是對需要操作的物體進行模組化的出發點,既對使用對象進行了抽象,隐藏了内部的細節(對使用的最終使用者而言)。使用者可以非常友善的使用class的方法、資料,而不用關心資料建立、運作邏輯的背後複雜的過程。我們以真實世界為例,當你騎一輛自行車的時候,不用考慮變速齒輪的原理如何驅動鍊條、車輪吧。
- 繼承(Inheritance):繼承是OOP概念中最流行的一個概念。繼承給程式員提供了可複用代碼的優勢。基類定義好函數邏輯,子類通過繼承,可實作直接通路--就想子類自身的方法一樣友善。
- 資料封裝(Data Encapsulation):對class的成員變量、成員函數通過通路控制符進行包裝,則稱為資料封裝。通路控制符有public、Protected、Private、Internal 4種類型。
- 多态(Polymorphism):對象可通過傳遞不同參數實作相同的動作,這種行為我們稱之為多态。我們以真實世界為例,“開車”這個方法,對不同類型的使用者要提供不同的參數實作多态,如Car.Drive(Man), Car.Drive(Woman)等。
- 消息通信(Message Communication):消息通信意味着通過通過消息進行class函數的調用、執行。
3 多态(Polymorphism)
在本節,我們分别用代碼片段來闡述各自類型的多态類型:函數重載、早期綁定、編譯器的多态。
先建立一個console 工程,并命名為
InheritanceAndPolymorphism,然後添加類Overload.cs,再添加DisplayOverload函數。
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();
運作程式,結果如下:
DisplayOverload 100
DisplayOverload method overloading
DisplayOverload method overloading100
Overload類中的DisplayOverload提供了3類不同的重載函數:方法名相同,參數類型和個數不同。C#中的這種方式成為重載,既我們不需要為每類函數定義不同名字的函數,僅需要改變函數參數類型和個數即可實作,這個也成為函數簽名。
用不同的傳回值可以否? 我們試試下面的代碼:
public void DisplayOverload() { }
public int
肯定的結果是,Visual Studio會給予如下的報錯資訊:
Error: Type 'InheritanceAndPolymorphism.Overload' already defines a member called 'DisplayOverload' with the same parameter types
從上面的結果可知:傳回值不作為多态函數簽名。
我們再運作如下的代碼:
static void DisplayOverload(int a) { }
public void DisplayOverload(int a) { }
public void DisplayOverload(string
結果依然是報錯:
Error: Type 'InheritanceAndPolymorphism.Overload' already defines a member called 'DisplayOverload' with the same parameter types
結論:static的可見函數修飾符不作為重載簽名。
運作下面的代碼,試試out、ref可否作為重載簽名。
private void DisplayOverload(int a) { }
private void DisplayOverload(out int a)
{
a = 100;
}
private void DisplayOverload(ref int
結果是如下的報錯:
Error: Cannot define overloaded method 'DisplayOverload' because it differs from another method only on ref and out
結論:ref、out傳遞參數修飾符也不能作為重載簽名。
4 多态中Params 參數的作用
一個函數可包含如下4種類型的參數傳遞:
- 值傳遞 (pass by value)
- 引用傳遞 (Pass by reference)
- 作為output參數 (As an output parameter)
- 使用參數數組 (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
在相同的作用域中,參數名稱必須是唯一的。
在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";
}
}
在Program.cs中添加如下代碼:
class Program
{
static void Main(string[] args)
{
Overload overload = new Overload();
overload.Display();
Console.ReadKey();
}
}
運作結果如下:
Akhil
Akhil 1
Akhil 2
Akhil3
結論:我們通過ref引用傳遞了name的記憶體位址,故修改x、y的值相當于直接修改name的值,故結果運作如上。
下面這段代碼示範了params關鍵字的作用:
在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動态參數數組機制,非常友善的在運作時動态傳遞不同數量的同類型參數。
注:params關鍵詞僅能作為函數的最後一個參數适用。
我們再試試params關鍵字的函數簽名和非params關鍵字函數簽名的優先級順序:
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();
}
}
運作結果如下:
parameterArray
The two integers 200 300
parameterArray
從運作結果看,C#非常巧妙的進行非params函數的精準比對優先,如1個int類型\3個int類型,則用params類型比對;2個int類型,用明确定義的函數進行比對。
5 結論
在本節中,我們進行OOP系列的第一篇,主要說明了編譯器的多态,它也稱為早期綁定或者方法重載。同時,我們也學習C#中威力強大的params關鍵字,并用它來實作多态。
本文要點歸納如下:
- C#函數重載的簽名規則是用參數的類型和數量判斷,而不是函數的名字。
- 函數傳回值不作為重載簽名。
- 修飾符不作為簽名的一部分,如static
- 同函數中,多個參數名稱要唯一
- ref、out是引用傳遞,傳遞的是參數的記憶體位址
- params 作為參數關鍵詞,僅能用于函數的最後一個參數
原文位址:http://www.codeproject.com/Articles/771455/Diving-in-OOP-Day-Polymorphism-and-Inheritance-Ear
本文是由葡萄城技術開發團隊釋出