C#基礎(2)
摘要:面向對象編程是很多編程語言的一種重要思想。萬物皆對象。有很多種不同個人理解,其實,用的多了,也就能夠去體會和領悟這種思想。個人理解:一個類或者接口, 就是對象,面向對象就是對類或者接口的操作,例如用到一個非靜態類,需要先new一個這個類的對象,繼承接口需要實現接口中的方法等。 此篇博客主要涉及到之前學習面向對象時的一些代碼筆記以及總結。
涉及內容: 1、裏氏替換原則 2、多態之虛方法 3、多態之抽象類 4、工廠設計模式 5、接口
----------------------------------------------------------------------------------------------------------------------------
面對對象(三大特征,五大原則):
三大特征:封裝、繼承、多態
五大原則:
單一原則: 一個對象應該只包含一個單一的職責,並且該職責被完整的封裝在一個類中。如果一個類中封裝了過多的職責,這些職責在並發執行的時候回相互幹擾
開放封閉原則: 對擴展開放,對修改代碼封閉(主要考慮安全性)
依賴倒轉原則: 高層(heigh leve1)模塊不該直接依賴低層(low leve1)模塊。它們兩個應該依賴抽象
裏氏替換原則: 子類能夠替換它們的父類
接口隔離原則: 客戶端不應該依賴那些它不需要的接口
-------------------------------------------------------------------------------------------------------------------------------
封裝:封裝類,封裝成方法 --解決代碼冗余
繼承:子類繼承父類
1、裏氏替換原則
a、子類可以賦值給父類
如果有一個方法需要一個父類作為參數,我們可以傳第一個子類對象 ,例如:需要一個object類型作為參數,可以傳遞任何類型的參數 (任何子類都繼承object)
b、如果父類中裝的是子類對象,則可以將這個父類強轉為子類對象
2、多態之虛方法
面向對象多態優點:①解決代碼冗余 ▲②:屏蔽各個子類之間的差異,寫出通用的代碼,適用於每個子類的調用
虛方法的使用:
//父類 public class Person
{ public string Name { get; set; }public Person(string name) { this.Name = name;
} public virtual void SayHello() { Console.WriteLine("我是人類"); } //子類① public class Chinese:Person { public Chinese(string name) : base(name) { } public override void SayHello() { Console.WriteLine("我是中國人,我叫{0}",this.Name); }
} //子類② public class America:Person { public America(string name) : base(name) { } public override void SayHello() { Console.WriteLine("我是美國人,我叫{0}",this.Name); } } //調用實例: Chinese ch = new Chinese("張三"); America a1 = new America("喬布斯"); Person[] per = { ch,a1 }; for (int i = 0; i < per.Length; i++) { per[i].SayHello();
} //結果: 兩個子類的SayHello方法
以上實例:將父類的方法標記為虛方法,使用關鍵字virtual,這個方法可以被子類重新寫一遍。
在父類的方法前面加上一個virtual,在子類的方法前面加上一個override;如果子類的方法前面不加override,編譯器不會報錯,但這樣的話,就無法通過父類來調用子類的方法,因為這個方法成了子類的獨有的方法,只是名字與父類相同而已,與父類無關。通過父類調用子類的方法,屏蔽子類之間的差異
3、多態之抽象類:(常用:工廠設計模式)
問題:運用多態求一個圓與矩形的面積 思考:圓的面積和矩形面積的求法不一樣,如何通過寫一個父類,然後調用父類的方法,屏蔽子類間的差異?父類根本無法構造方法體
//父類: public abstract class Graph { public abstract double Getarea(); //抽象類沒有方法實體 } //子類①:圓 public class Circle : Graph { public double R { get; set; } public Circle(double r) { this.R = r; } public override double Getarea() { return Math.PI * R * R; } } //子類②:矩形 public class Rectangle : Graph { public double Hight { get; set; } public double Width { get; set; } public Rectangle(double width, double hight) { this.Width = width; this.Hight = hight; } public override double Getarea() { return Width * Hight; } } //調用實例: Graph gh = new Circle(3) double circlearea= gh.Getarea(); //求圓的面積 Graph gh2 = new Rectangle(2, 4.2); double rearea = gh2.Getarea(); //求矩形面積
抽象類的特點:
a、抽象類中的抽象成員必須標記為abstract,並且不能有任何實現。方法不能有任何實現是指,方法沒有大括號,也沒有方法體。 只有大括號,沒有方法體的方法叫做空實現。
b、抽象成員必須標記在抽象類中
c、抽象類是有構造函數的,但抽象類不能被實例化
d、子類繼承抽象類後,必須把父類中的所有抽象成員都重寫。(除非子類也是一個抽象類,則可以不重寫)
e、在抽象類中可以包含實例成員,並且它們可以不被子類實現
以上實例說明:不知道如何去寫父類這個方法,通過new子類實現抽象方法,屏蔽子類間的差異。上面簡單用下抽象類,常用於:工廠設計模式
4、工廠設計模式:
參與者:Product:抽象產品類,將具體產品類的公共代碼抽象和提取後封裝在一個抽象產品類中(抽象類的抽象方法)
Concerteproduct:具體產品類,將需要創建的各種不同產品對象的相關代碼封裝到具體產品類中 (繼承抽象類的子類的各自方法)
Factory:工廠類,提供一個工廠類創建各種產品,在工廠類中提供一個創建產品的方法,該方法可以根據傳入的參數不同創建不同的產品對象
Client: 客戶端類,只需要調用工廠類的工廠方法,傳入相應的方法即可獲得產品對象(實現)
5、接口:
特點:a、接口是一種規範 只要一個類繼承了一個接口,這個類必須實現接口的所有成員
b、接口不能被實例化 也就是說不能創建對象
c、接口與接口之間可以繼承 並且可以多繼承,接口不能繼承一個類
d、接口中的成員不能加訪問修飾符 默認為public
接口作用很大:首先實現了多繼承,另外常用:不同層之間通過調用接口提高安全性(例:業務邏輯層調用數據會話層的接口)。
實現 發布訂閱模式(觀察者模式):我們作為訂閱者不必每次都去查看這個公眾號有沒有新文章發布, 公眾號作為發布者會在合適時間通知我們(繼承接口)
我們與公眾號之間不再強耦合在一起。公眾號不關心誰訂閱了它,不管你是男是女還是寵物狗,它只需要定時向所有訂閱者發布消息即可(遍歷訂閱者)
總結:什麽時候用虛方法來實現多態?什麽時候用抽象類來實現多態?什麽時候用接口來實現多態?
在我提供給你的幾個類當中,如果說你能抽象出來一個父類,並且這個父類必須寫上這幾個子類共有的方法,然後你還不知道怎麽去寫這個方法,就用抽象類來寫這個多態。
反之,抽象出來的父類,方法可以寫,並且我還要創建這個父類的對象,就用虛方法。
這幾個類裏面根本就找不出來父類,但它們都有一個共同的行為,共同的能力。這個時候就用接口來實現多態
面向對象多態確實是一個很抽象的東西,具體運用可以根據需求,根據業務邏輯去選擇使用。
C#基礎(2)