類與實例 •對象:一切事物皆對象,對象就是一個 自包含的實體,用一組可識別的特性和行為來標識 •類:具有相同的屬性和功能的對象的抽象的集合 1、定義類 1 class Cat 2 { 3 public string Shout() 4 { 5 return "喵"; 6 } 7 } 註:“這裡的'c ...
類與實例
•對象:一切事物皆對象,對象就是一個 自包含的實體,用一組可識別的特性和行為來標識
•類:具有相同的屬性和功能的對象的抽象的集合
1、定義類
1 class Cat 2 { 3 public string Shout() 4 { 5 return "喵"; 6 } 7 }View Code
註:“這裡的'class'是表示定義類的關鍵字,'Cat'就是類的名稱,'Shout'就是類的方法。”
註意事項:第一,類名稱首字母要大寫。多個單詞則各個首字母大寫;第二,對外公開的方法需要使用'public'修飾符
•實例:就是一個真實的對象,比如我們都是'人',而你和我其實就是‘人’類的實例了,而實例化就是創建對象的過程,使用new關鍵字來創建
1 private void button1_click(object sender,EventArgs e) 2 { 3 Cat cat=new Cat(); //將Cat類實例化 4 MessageBox.Show(cat.Shout()); 5 }View Code
註:“'Cat cat=new Cat();'其實做了兩件事。”
1 Cat cat; //聲明一個Cat對象,對象名為cat 2 cat=new Cat(); //將此cat對象實例化View Code
“Cat實例化後,等同於出生了一隻小貓cat,此時就可以讓小貓cat.Shout()了,在任何需要小貓叫的地方都可以實例化它。”
2、構造函數
•構造函數又叫‘構造方法’,其實就是對類進行初始化。構造方法與類名同名,無返回值,也不需要void,在new時候調用
2.1、有參構造函數
1 class Cat 2 { 3 private string name = "";//聲明Cat類的私有字元串變數name 4 public Cat(string name) //定義Cat類的構造方法,參數是輸入一個字元串 5 { 6 this.name = name; //將參數賦值給私有變數name 7 } 8 public string Shout() 9 { 10 return "我的名字叫:" + name + " 喵"; 11 } 12 }View Code
2.2、有參構造函數調用
1 private void button1_Click(object sender, EventArgs e) 2 { 3 Cat cat = new Cat("咪咪"); 4 MessageBox.Show(cat.Shout()); 5 }View Code
2.3、方法的重載
•方法重載提供了創建同名的對個方法的能力,單這些方法需要 使用不同的參數類型
1 class Cat 2 { 3 private string name = "";//聲明Cat類的私有字元串變數name 4 public Cat(string name) //定義Cat類的構造方法,參數是輸入一個字元串 5 { 6 this.name = name; //將參數賦值給私有變數name 7 } 8 public Cat() //將構造方法重載 9 { 10 this.name = "無名"; 11 } 12 public string Shout() 13 { 14 return "我的名字叫:" + name + " 喵"; 15 } 16 }View Code
註:方法的重載,兩個方法必須要方法名相同,但參數類型或個數必須要有所不同,否則就沒有意義了。方法重載可在不改變原方法的基礎上,新增功能,算是提供了函數可擴展的能力。
2.4、屬性與修飾符
•屬性:是一個方法或一對方法,但在調用他的代碼來看,他是一個欄位,即屬性適合於欄位的方法使用方法調用的場合。欄位是存儲類要滿足其設計所需要的數據,欄位是與類相關的變數
1 private int shoutNum = 3; //聲明一個內部欄位,註意是private,預設叫的次數為3 2 public int ShoutNum //ShoutNum屬性,註意是public 3 { 4 get 5 { 6 return shoutNum; //當中有兩個方法get表示外界調用時可以得到shoutNum的值 7 } 8 9 set 10 { 11 shoutNum = value; //set表示外界可以給內部的shoutNum賦值 12 } 13 }View Code
•public:表示它所修飾的類成員可以允許其他任何類來訪問,俗稱公有的
•private:表示只允許同一個類中的成員訪問,其他類包括它的子類無法訪問,俗稱私有的
註:如果在類的成員沒有加修飾符,則被認為是private的。
屬性的兩個方法:
get:訪問器返回與聲明的屬性相同的數據類型,表示的意思是調用時可以得到內部欄位的值或引用
set:訪問器沒有顯示設置參數,但它有一個隱式參數,用關鍵字value表示,他的作用是調用屬性時可以給內部的欄位或引用賦值
3、面向對象
3.1、封裝
•解釋:每個對象都包含它能進行操作所需要的所有信息
•優點:
1、良好的封裝能夠減少耦合,至少我們讓Cat和Form1的耦合分離。
2、類內部的實現可以自由地修改。
3、類具有清晰的對外介面
3.2、繼承
•解釋:對象的繼承代表 了一種‘is-a’的關係,如果兩個對象A和B,可以描述為‘B’是‘A’,則表明B可以繼承A,繼承者還可以理解為對被繼承者的特殊化,因為他除了具備被繼承者的特性外,還具備自己獨有的個性。繼承定義了類如何相互關聯,共用特性。繼承的工作方式是,定義父類和子類,或叫做基類和派生類,其中子類繼承父類的所有特性。子類不但繼承了父類的所有特性,還可以定的定義新的特性。
•三句便於更好地理解繼承概念
1、子類擁有父類非private的屬性和功能
2、子類具有自己的屬性和功能,即子類可以擴展父類沒有的屬性和功能
3、子類還可以以自己的方式實現父類的功能(方法的重寫)
我們來看一下貓和狗有那些共同特性,他們都屬於動物,並且都有屬於自己的名字,都會叫等等。
父類:
1 class Animal 2 { 3 protected string Name = ""; //註意訪問修飾符為protected:表示繼承時子類可以對基類有完全訪問權 4 public Animal(string name) 5 { 6 this.Name = name; 7 } 8 public Animal() 9 { 10 this.Name = "無名"; 11 } 12 protected int shoutNum = 3; //註意訪問修飾符為protected 13 14 protected int ShoutNum 15 { 16 get 17 { 18 return shoutNum; 19 } 20 21 set 22 { 23 shoutNum = value; 24 } 25 } 26 }View Code
基類:
貓類:
1 class Cat:Animal //繼承格式---> 子類:父類 2 { 3 public Cat() : base() //子類構造方法需要調用父類同樣參數類型的構造函數,用base關鍵字代表父類 4 { 5 } 6 public Cat(string name) : base(name) 7 { 8 } 9 public string Shout() 10 { 11 string result = ""; 12 for (int i=0;i<shoutNum;i++) 13 { 14 result += "喵,"; 15 } 16 return "我的名字叫"+Name+" "+result; 17 } 18 }View Code
狗類:
1 class Dog:Animal //繼承格式---> 子類:父類 2 { 3 public Dog() : base() //子類構造方法需要調用父類同樣參數類型的構造函數,用base關鍵字代表父類 4 { 5 } 6 public Dog(string name) : base(name) 7 { 8 } 9 public string Shout() 10 { 11 string result = ""; 12 for (int i=0;i<shoutNum;i++) 13 { 14 result += "汪,"; 15 } 16 return "我的名字叫"+Name+" "+result; 17 } 18 }View Code
註:子類從它的父類中繼承的成員有方法、域、屬性、事件、索引指示器,但對於構造方法,有一種特殊,他不能被繼承,只能被調用,對於調用父類的成員,可以使用base關鍵字。
如果還有動物類的話,按照以前的寫法就需要再複製N遍,不用繼承的話,如果要修改功能,就必須在所有重覆的方法中修改,代碼越多,出錯的可能就越大,而繼承的有點是,繼承使得所有子類公共的部分都放在了父類,使得代碼得到了共用,這樣就避免了重覆,另外,繼承可使得修改或擴展繼承而來的實現都較為容易。
繼承是有缺點的,那就是父類變,則子類不得不變,另外繼承會破壞包裝,父類實現細節暴露給子類,這其實是增大了兩個類之間的耦合性。
3.3、多態
•解釋:表示不同的對象可以執行相同的動作,但要通過它們自己的實現代碼來執行
下麵通過過一個小故事,更好的理解多態的定義
我們的國粹‘京劇’以前都是子承父業,代代相傳的藝術。假設有這樣一對父子,父親是非常有名的京劇藝術家,兒子長大成人了,模仿父親的戲也惟妙惟肖。有一天,父親突然發高燒,上不了台邊沿,而票都早就賣出,退票顯然會大大影響聲譽。怎麼辦呢?由於京戲都是需要化妝才可以上臺的,於是就決定讓兒子代父親上臺表演。化妝後誰還認識誰呀,只要長得好久可以混弄過去了。這裡面有幾點註意:第一、子類以父類的身份出現,兒子代表老子表演,化妝後就是以父親身份出現了。第二、子類在工作時以自己的方式來實現,兒子模仿得再好,那也是模仿,兒子只能用自己理解的表現方式去模仿父親的作品。第三、子類以父類的身份出現時,子類特有的屬性和方法不可以使用,兒子經過多年學習,其實已經有了自己的創作,自己的絕活,但在此時,代表父親表演時,絕活是不能表現出來的,當然,如果父親還有別的兒子會表演,也可以在此時代表父親上場,道理也是一樣。這就是多態。
•虛方法
解釋:為了使子類的實例完全接替來自父類的類成員,父類必須將該成員聲明為虛擬的。這是通過在該成員的返回類型之前添加virtual關鍵字來實現。然後,子類可以選擇使用override關鍵字,將父類實現替換為它自己的實現,這就是方法重寫override,或者叫做方法覆寫。
父類:
1 class Animal 2 { 3 ....... 4 public virtual string Shout() // 註意修飾符中增加了一個virtual,它表示此方法是虛方法,可以被子類重寫 5 { 6 return ""; 7 } 8 }View Code
子類:
1 class Dog:Animal //繼承格式---> 子類:父類 2 { 3 public Dog() : base() //子類構造方法需要調用父類同樣參數類型的構造函數,用base關鍵字代表父類 4 { 5 } 6 public Dog(string name) : base(name) 7 { 8 } 9 public override string Shout() //註意增加了override,表示方法重寫 10 { 11 string result = ""; 12 for (int i=0;i<shoutNum;i++) 13 { 14 result += "汪,"; 15 } 16 return "我的名字叫"+Name+" "+result; 17 } 18 }View Code
多態的原理:當方法被調用時,無論對象是否被轉換為其父類,都只有位於對象繼承鏈最末端的方法實現會被調用。也就是說,虛方法是按照其運行時類型而非編譯時類型進行動態綁定調用的。沒有學過設計模式,那麼對多態、乃至對面向對象的理解多半都是膚淺和片面的。我相信會有那種天才,可以聽一知十,剛學的東西就可以靈活自如地應用,甚至要造汽車,他都能再去發明輪子。但對於絕大多數程式員,還是需要踏踏實實地學習基本的東西,併在不斷地實踐中成長,最終成為高手。