上一章筆者講到關於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#時候應該明白的一些地方。我們可以看到差別不大的繼承。封裝和多態還是有一定的差別。同是就是構造函數上的一些差別。