上一章筆者講到關於ADO.NET相關的知識,知道了如何去訪問數據庫。本章將來講關於面向對象的思想。不管在JAVA還是在C#面向對象思想的重要性都是占了一個很大的成份。往往他就像呼吸一樣子,更多的時候我們會忽略。面向對象編程有三大特性:封裝、多態、繼承。關於這三大特性的定義筆者不會過多的介紹。網絡上類似這樣子的文章一搜一片。相信裡面肯定有你需要的。而本系列主要目標是想讓JAVA程序員進入C#的開發環境。所以更多會在倆者之間的差別進行講解。
類和對象在進入面向對象思想的講解之前,筆者認為應該先明白什麼是類,什麼是對象,及他們之間的關系。這樣子的話才能更加明白面向對象思想。相關類和對象的講解在網絡上一搜也是一大片資料。筆者不想過多的解講。筆者只是把自己的理解寫出來,希望能給大家一些幫助。通常筆者喜歡把類理解為建房子時候用到的房子結構圖紙。而對象便是根據房子結構圖紙而建造成功的房子。這裡的圖紙便是.cs文件,圖紙上面的結構圖就是類了。而建造成功的房子便是對象,也就是內存中的實例。這是筆者的理解。有了這一個之後,我們就來看一下三大特性。
面向對象的封裝對於封裝的裡面,筆者是這樣子看的。如果有過面向過程開發的讀者們就會明白。所謂的封裝就是把相關的數據放在同一個區域的,然後給這個區域命個名字。這樣子將來開發的時候就可以知道來源。代碼中的那個“.”就是最好的證明了。筆者不想講過多沒有用的話。我們就以代碼的形式來學習。如下
C#:
1 public class Person 2 { 3 public string Name { set; get; } 4 5 public string Sex { set; get; } 6 7 public void Move() 8 { 9 10 } 11 }
筆者定義一個叫Person的類。顯然最大的區別在代碼的中的“{ set; get; }”這一個部分。相信JAVA中我們常常會看到一些習慣的寫法。算了。為了方便閱讀筆者還是寫代碼貼出來吧。
JAVA:
1 public class Person { 2 3 private String name; 4 private String sex; 5 6 public String getName() { 7 return name; 8 } 9 public void setName(String name) { 10 this.name = name; 11 } 12 public String getSex() { 13 return sex; 14 } 15 public void setSex(String sex) { 16 this.sex = sex; 17 } 18 19 public void Move() 20 { 21 22 } 23 24 }
我們可以看到JAVA這邊如果類外面的想要用內部成員的話,就必須通過對應的set或get方法來實現。而在C#中卻沒有這樣子寫法。他有自己一個概念叫屬性。上面的C#代碼就是屬性的寫法。只不過他還是縮寫的。為了學習我們還是在看一下正真的寫法吧。
C#:
1 public class Person 2 { 3 private string _name; 4 private string _sex; 5 public string Name 6 { 7 set { this._name = value; } 8 get { return this._name; } 9 } 10 11 public string Sex 12 { 13 set { this._sex = value; } 14 get { return this._sex; } 15 } 16 17 public void Move() 18 { 19 20 } 21 }
上面的代碼就是C#屬性的完整寫法。可是C#開發人員往往不喜歡用而以。我們還都清楚知道JAVA在給類的內部成員變量賦值的時候,可能會做一些判斷或處理。 對應的C#這邊你們看到set後面的大括號了沒有。就是在大括號裡面寫。其中關鍵字value就是將來外面傳進來的值。代碼如下
C#:
1 public string Name 2 { 3 set 4 { 5 if (string.IsNullOrWhiteSpace(value))//判斷傳進來的值是不是空的。其中包括空格鍵 6 throw new ArgumentNullException("名字不能賦空值"); 7 this._name = value; 8 } 9 get { return this._name; } 10 }
C#屬性的使用:
Person person = new Person(); person.Name = "Aomi"; person.Move();
在我們建設類的時候,往往會定義一個叫常量的成員。JAVA用是關鍵字final來實現。而C#用的是關鍵字const。當然這裡還有一個關鍵字readonly。從某種意義來講他跟常量有一點類似。但又不能說是常量。只能說是一個只讀的變量成員。並且他們倆個在賦值的時候又有很大的差別。如下
關鍵字const:在定義的時候就要給也賦值。
關鍵字readonly:在定義的時候就要給也賦值。同時候在構造函數裡面。
C#:
private readonly string Nick ="aaa"; public const string DefaultName = "Person";
除了賦值和定義不同之外,還有明白他們在使用的時候也不同。關鍵字const是用類來使用。如 Person.DefaultName。但是關鍵字readonly是對象內部自己的。這一點要注意。
當我們把數據封裝成為一個類的時候,我們要用這個類就必須跟類的構造函數打交道。這裡有著跟JAVA一個很大差別。如下代碼
C#:
public Person():this("Aomi") { } public Person(string name) { this.Name = name; }
從上面的代碼我們就能明白:JAVA的寫法是寫在構造函數裡面。而C#卻是在函數名後面。注意思加上“:”。
面向對象的繼承關於繼承的話,大多數跟JAVA沒有多的差別。主要是extends和implements都要用“:”來寫了。這一點到是比較JAVA簡單一點。而值得注意還有一點那便是跟構造函數有關系。我們都知道JAVA的super關鍵字吧。C#是用base關鍵字。同時用法不同。如下
public class Child : Person { public Child() : base("Aomi") { } }
筆者想了一會兒,覺得好像繼承這邊沒有別的不同了。
面向對象的多態筆者個人覺得JAVA在多態這邊可能理解起來比較簡單。為什麼這樣子講呢?我們知道多態分為重寫和重載。其中最大的差別是在重寫身上。
1.重載。即是一名多用的意思。語法跟C#一樣子。必須要方法名相同,但是參數類型或是個數不同。
2.重寫。意思跟JAVA一樣子。只是寫法上卻有很大的不同。
C#的Person類:
1 public class Person 2 { 3 4 private string _name; 5 private string _sex; 6 public readonly string Nick ="aaa"; 7 public const string DefaultName = "Person"; 8 9 public Person():this("Aomi") 10 { 11 12 } 13 public Person(string name) 14 { 15 this.Name = name; 16 } 17 public string Name 18 { 19 set 20 { 21 if (string.IsNullOrWhiteSpace(value))//判斷傳進來的值是不是空的。其中包括空格鍵 22 throw new ArgumentNullException("名字不能賦空值"); 23 this._name = value; 24 } 25 get { return this._name; } 26 } 27 28 public string Sex 29 { 30 set { this._sex = value; } 31 get { return this._sex; } 32 } 33 34 public void Move() 35 { 36 Console.WriteLine("person move"); 37 } 38 }
C#的Child類:
1 public class Child : Person 2 { 3 public Child() 4 : base("Aomi") 5 { 6 7 } 8 public void Move() 9 { 10 Console.WriteLine("child move"); 11 } 12 }
C#的Program類:
class Program { static void Main(string[] args) { Person person = new Child(); person.Name = "Aomi"; person.Move(); } }
執行結果:
我們看到上面代碼的執行結果是:person move。Child類重寫了Person類的Move方法,在用Person類包裝Child類實例。筆者用類似的功能在JAVA做了實驗發現執行結果是:child move。在C#這裡事實到關系到三個關鍵字:virtual、new、override。上面C#代碼中Child類的Move方法事實上是 public new void Move()。也就是說沒有重寫原來父類的方法。所以在執行用Person類包裝Child類實例的時候,會執行Person類的方法。所以C#這邊重寫的用法。應該是如下面這樣子。
C#的Person類:
public class Person { public virtual void Move() { Console.WriteLine("person move"); } }
C#的Child類:
public class Child : Person { public override void Move() { Console.WriteLine("child move"); } }
看到了吧。父類如果將來有方法可能會被重寫的話,最好用關鍵字virtual來修飾這個方法。同樣子子類要重寫父類的話,就必須用關鍵override。至於關鍵new就是重新子類自己在寫一個方法,不影響父類。
本章總結本章主要講到面向對象在C#時候應該明白的一些地方。我們可以看到差別不大的繼承。封裝和多態還是有一定的差別。同是就是構造函數上的一些差別。