一:面向對象的基本知識html
C#程序分爲面向過程和麪向對象編程
什麼是對象:一切皆爲對象:Object,生活中常說的「東西」就是程序裏面所指的對象;生活中遇到的東西咱們都在下意識的歸類;歸類意味着抽象模型;安全
類:class,對某類衆多對象的共同特色抽象出來的模型。less
他們的關係:類是好多對象的抽象,對象是類的實例化。dom
建立一個名爲Dog的類:編程語言
class Dog //通常首字母大寫 { int age; public void setage(int a) //用方法賦值 { age = a; } public void buck() { Console.WriteLine("這是一個方法"); } }
類中通常包括兩類東西,變量(名詞,也交成員變量這裏age是成員變量)和函數(動詞,也叫成員函數或成員方法 buck()就是方法)。ide
對象實例化:函數
Dog d1 = new Dog();
這樣就實例化出了一個Dog的對象a。工具
例子:兩個套在一塊兒的圓,求內圓的周長和內圓與外圓之間的面積,用面向對象的思想作post
class circle { float r; public circle(float a) { r = a; } public double zhouchang() { return 2 * 3.14 * r; } public double mianji() { return 3.14 * r * r; } } class Program { static void Main(string[] args) { circle m = new circle(10); circle n = new circle(20); double bc = m.zhouchang(); double mj = (n.mianji()-m.mianji()); Console.WriteLine("內圓的周長爲:"+bc); Console.WriteLine("花磚的面積爲:"+mj); } }
首先作了一個名爲circle的類,它能夠生產任何一個半徑不一樣的圓,在構造函數中,爲半徑賦值。
二:面向對象的三大特性
三大特性是指:封裝,繼承,多態。
類中的方法通常分爲:構造方法(函數);屬性方法(函數):成員變量賦值取值;行爲方法(函數):變量運算。
(一): 封裝
1.封裝含義:
(1)不一樣類的變量只屬於各自的類。
(2)不一樣對象的成員變量只屬於各自的對象,彼此不受影響。
(3)對象中的變量須要經過方法(函數)實現操做,比較安全。
封裝爲了安全,儘可能不用public來聲明變量,避免在main函數中能夠直接訪問賦值而下降了安全性,在類中創建public的方法來賦值,main中調用此方法傳值。
2. 成員變量及訪問修飾
private 私有成員 ,protected 受保護的成員,public 公有成員
3. 構造函數
它是一個特殊的成員函數,通常在構造函數裏進行初始化。若是不寫構造函數在new的時候會自動生成一個默認空的構造函數。
寫法特殊:沒有返回值,函數名只能與類名同樣;public 類名(){};
執行特殊:類在實例化(new出來的時候)自動執行,構造函數是最先執行的成員函數,構造函數是用來生成對象的函數。
它的主要做用:對象實例化生成的時候,作一些初始化的工做。
下面例子就是作了一個Ren()的構造函數,爲其變量賦上初始化的值:
class Ren { string _Name; int _Age; public Ren() { _Name = "龍神"; _Age = 25; } }
4. 重載(函數或方法)
函數名相同,參數不一樣(參數個數或類型不一樣)的多個函數就造成了重載。
重載只與函數名和形參有關,與返回類型無關。
下面舉個例子,構造函數的重載:
class Ren() { string _Name; int _Age; public Ren() { _Name = "ZSMJ"; _Age = 25; } public Ren(string name) { _Name = name; } public Ren(string name,int age) { _Name = name; _Age = age; } }
這樣Ren類中就作了三個構造函數,第一個是無參的,第二個是一個string類型的參數,第三個是兩個參數,類型分別爲string和int。他們符合重載的條件,因此會造成重載在Main函數中new的時候根據參數的不一樣會自動選擇執行其中一個構造函數。
若是在Main函數中:
Ren a = new Ren("王大錘");
則執行的構造函數是第二個。
5. 屬性
它的聲明:public 類型 屬性名;也能夠選擇成員變量右鍵重構,封裝字段來生成屬性方法,例如:
string _Name; public string Name { get { return _Name; } set { _Name = value; } }
這樣Name就是該類的一個屬性,在Main函數中能夠用此屬性爲其成員變量賦值取值:
Ren a = new Ren("王大錘"); a.Name = "王尼瑪";
注意:(1)屬性是用來爲成員變量賦值和取值的,它有代替屬性方法的做用,通常用屬性。
(2)屬性定義的時候,屬性名後面沒有小括號。
(3)屬性都是public。
(4)屬性中只能包含兩個部分:get和set。代碼也只能寫在get和set的花括號裏面。
(5)屬性分爲只讀屬性,只寫屬性和可讀寫屬性,與get和set的有無有關係。
6. this關鍵字
概念:this引用,this在哪一個對象裏面執行表明該對象自己。
用法:this.成員變量(成員方法),this._Name; this.Eat();
例子:this 調用當前對象的其它構造函數。
public class Mydate { int _Year; int _Month; int _Day; int _Hours; public Mydate(int year,int month) { _Year = year; _Month = month; } public Mydate(int year,int month,int day,int hours): this(year,month) { _Day = day; _Hours = hours; } }
這裏第一個構造函數中有兩個參數year和month,在作第二個構造函數的時候爲了方便用「:this」來調用了本類中第一個構造函數,這樣第二個構造函數只需寫後day和hours的執行語句就能夠了。
在new的時候傳入不一樣的參數,會實例出不一樣的對象,這時候的this就表明不一樣的對象。
7. is關鍵字(運算符)
用法:對象 is 類名;is左邊是對象,右邊是類型;
Console.WriteLine(a is Ren);
若是a是一個Ren類的對象,則返回值爲true,不然返回值爲false。
8. partial關鍵字
若是一個類特別大,不宜擋在一個文件中實現或者一個類中有一部分代碼不宜與其餘混淆或者須要多人合做編寫一個類,這就須要將一個類拆開來寫。
非靜態變量稱爲實例變量,非靜態方法稱爲實例方法,實例成員的數據存在每一個對象中,用對象名來調用。
靜態成員包括:靜態變量,靜態屬性,靜態方法。
定義一個成員爲靜態的:在變量或方法前加static,如:static int a;
靜態變量是屬於類的,每一個對象都有的而且相同的東西只保存一份,不和實例變量那樣在每一個對象裏都面保存一份。
能夠說它不屬於任何對象,也能夠說它又屬於任何一個對象,給每一個對象用,節省空間。
例如:每包粉筆的顏色是靜態成員,每支粉筆的剩餘長度是實例成員。
靜態變量或方法不須要new出來。
在C#中,定義了一個粉筆的類:
class Fenbi { static string _Color; public static string Color { get { return Fenbi._Color; } set { Fenbi._Color = value; } } int _Lenght; public int Lenght { get { return _Lenght; } set { _Lenght = value; } } }
(1)在當前類的花括號外,靜態成員只能用類名來調用,不能用對象名來調用,而實例成員只能用對象名來調用,不能用類名來調用。
Fenbi.Color ="Yellow"; Fenbi b = new Fenbi(); b.Lenght = 10;
(2)在當前類的花括號內,靜態方法只能直接調用靜態成員,不能調用非靜態成員,實例方法能夠調用非靜態和靜態的成員。
public static void xiezi() { Console.WriteLine("寫出"+_Color+"的文字了"); }
public void change() { Console.WriteLine(_Color+"的粉筆長度變爲:"+_Lenght); }
10. 拷貝
淺拷貝:傳遞引用,不賦值對象。
深拷貝:建立一個新的對象。
(二): 繼承
1. 語法:public 子類名:父類名;如:class Dog:Pet。
2. 特色:單繼承,一個父類能夠派生多個子類,但每一個子類只能有一個父類
若是一個類,沒有明確指定父類是誰,默認是object。除了object類以外,全部類都有一個父類。
子類能夠從父類繼承下父類的成員變量和成員方法。
3. 訪問修飾符合訪問權限:
private 的成員不被繼承,只能在該類中訪問。
protected成員能夠被繼承,能在該類和派生類中訪問到,在外界訪問不到。父類中的變量通常用protected。
public成員能夠被繼承,能在全部地方訪問到。
4. base 關鍵字:子類中能夠用(base.父類中的成員 )來調用父類中的成員,base()調用父類構造,base.xxx()調用父類成員方法。
調用的參數值會被覆蓋,方法也會被覆蓋。
5. 繼承關係中實例化子類的流程:
先執行父類的構造函數,再執行子類的構造函數。
6. 繼承關係的實例化:
若是父類的構造函數沒有空參構造函數,全是帶參數的,則子類必需要寫構造函數,構造函數的形參中必須包含父類構造函數所須要的參數,還要用base()把父類構造函數所須要的參數傳遞父類。
例如:父類中只有這個構造函數
public Ren(string name, int age) { _Name = name; _Age = age; }
那麼子類中的構造函數應該這樣寫:
public Chinese(string name, int age, string yuyan):base(name,age) { _Yuyan = yuyan; }
7. sealed 關鍵字:
若是用來修飾class,稱爲密封類,此類沒法被繼承;若是用來修飾方法,該方法沒法被重寫。
如: sealed class Ren{};
(三): 多態
1. 概念:父類引用指向不一樣子類實例的時候,父類引用所調用的函數都是子類的函數,因爲子類對象不一樣,父類引用調用的成員表現出來的不一樣狀態就是一種多態。
2. 實現的方式:多態須要經過繼承來實現
3. 分類:分爲編譯多態(重載overload)和運行多態(重寫override)。父類方法被重寫了以後也能夠在子類中用base.方法 調用。
4. virtual關鍵字:虛方法,允不容許重寫,要重寫父類方法必須是虛方法:public virtual void Eat()。
5. 運行多態實現的條件:
(1)子類對父類方法的重寫(override),父類和子類中都有相同的方法。
(2)父類引用指向子類實例。
例如,有一個Ren類是父類,一個Chinese類和American是子類,Ren r = new Chinese();父類的引用 r 指向子類實例。
class Ren { protected string _Name; protected string _Country; public virtual void Eat() { Console.WriteLine("正在吃飯..."); } } class American : Ren { public override void Eat() { Console.WriteLine("正在用叉子和刀子吃飯...."); } } class Chinese : Ren { public override void Eat() { Console.WriteLine("正在用筷子吃飯..."); } }
父類Ren中有個Eat方法爲虛方法,在子類Chinese和American中進行了重寫,在Main函數中:
Random rand = new Random(); int n = rand.Next(100); Ren a; if (n % 2 == 0) { a = new American(); } else { a = new Chinese(); } a.Eat();
隨機讓父類引用 a 指向 不一樣的子類實例,這樣用父類引用 a 調用方法Eat()的時候表現出不一樣對象的操做。
6. 里氏代換原則和抽象依賴原則
里氏代換原則,若是某個方法接收的是父類引用,能夠向裏面傳父類或其子類的元素,子類對象替代父類對象。
抽象依賴原則,用父類的引用來指向子類的實例。
例子:怪獸吃人,傳入Ren的引用 r ,則r.Cry()表現出來不一樣的結果。
class Monster { public void EatFood(Ren r) //r = a; { r.Cry(); Console.WriteLine("人類真好吃,吃飽了!"); } } class Ren { public virtual void Cry() { Console.WriteLine("......."); } } class American:Ren { public override void Cry() { Console.WriteLine("MyGod,God bless me!"); } } class Chinese:Ren { public override void Cry() { Console.WriteLine("天哪,老天爺保佑我!"); } }
在Main函數中 ,先實例出一個怪獸,隨機生成一個Ren的對象,將此對象的引用傳入怪獸類裏,經過這個引用來表現出不一樣的狀態。
Monster m = new Monster();
Random rand = new Random(); int n = rand.Next(100); if (n % 2 == 0) { American a = new American(); //或者是這樣寫 Ren a = new American(); m.EatFood(a); } else { Chinese c = new Chinese(); //或者是這樣寫 Ren c = new Chinese(); m.EatFood(c); }