天天看點

面向對象程式設計理論知識與思想(oop的思想與原則)

面向對象程式設計理論知識與思想(oop的思想與原則)

第一部分:oop理論基礎

對象:對象是一個自包含的實體,用一組可識别的特性和行為來辨別。

面向對象程式設計(Object-Oriented Programming,OOP)其實就是針對對象程式設計。

類:類就是具有相同的屬性和功能的對象的抽象的集合。

第一,類名稱首字母要大寫。

第二,對外公開的方法需要用 "public"修飾符。

執行個體就是一個真實的對象。執行個體化就是建立對象的過程,使用new關鍵字建立。

構造方法,又叫構造函數,其實就是對類進行初始化。構造方法與類同名,無傳回值,也不需要void,在new時候調用。

所有類都有構造方法,如果你不編碼則系統預設生成空的構造方法,若你有定義自己的構造方法,那麼預設的構造方法就會失效。

方法重載提供了建立同名的多個方法的能力,但這些方法需要使用不同的參數類型。

方法重載時,兩個方法必須要方法名相同,但參數類型或個數必須要有所不同。方法重載可在不改變原方法的基礎上,新增功能。

屬性成字段:屬性是一個方法或一對方法,但在調用它的代碼看來,它是一個字段,即屬性适合于以字段的地方使用方法調用的場合。字段是存儲類要滿足其設計所需要的資料,字段是與類相關的變量。通常屬性是公有的,字段是私有的。

屬性有兩個方法get和set,隻有get時表示是隻讀屬性。

修飾符:

public 表示它所修飾的類成員可以允許其它任何類來通路,俗稱公有的。

private 表示隻允許同一個類中的成員通路,其它類包括它的字類無法通路,俗稱私有的。

protected 表示繼承時子類可以對基類有完全通路權,即對子類公開,但不對其它類公開。

封裝:每個對象都包含它能進行操作所需要的所有資訊,這個特性稱為封裝。是以對象不必依賴其它對象來完成自己的操作。

封裝的好處:

第一,良好的封裝能減少耦合

第二,類内部的實作可以自由地修改

第三,類具有清晰的對外接口

繼承:對象的繼承代表了一種'is-a'的關系。如果兩個對象A和B,可以描述為'B是A‘,則表明B可以繼承A。

繼承者還可以了解為是對被繼承者的特殊化,因為它除了具備繼承者的特性殩,還具備自己獨有的個性。

繼承定義了類如何互相關聯,共享特性。繼承的工作方式是,定義父類和子類,或叫基類和派生類,其中子類繼承父類的所有特性。子類不但繼承了父類的所有特性,還可以定義新的特性。

學習繼承最好是記住三句話:如果子類繼承于父類,

第一,子類擁有父類非private的屬性和功能

第二,子類具有自己的屬性和功能,即子類可以擴充父類沒有的屬性和功能

第三,子類還可以以自己的方式實作父類的功能(方法重寫)

子類從它的父類中繼承的成員有方法,域,屬性,事件,索引訓示器,但對于構造方法,有一些特殊,不能被繼承,隻能被調用。對于調用父類的成員,可以用base關鍵字。

如:

class Cat : Animal
 {
  public Cat() : base()
  { }
  public Cat(String name) : base(name)
  {
   
  }
  ...
 }      

不用繼承的話,如果要修改功能,就必須在所有重複的方法中修改,代碼越多,出錯的可能性就越大,而繼承的優點是,繼承使得所有子類公共的部分都放在了父類,使得代碼得到了共享,

就避免了重複,另外,繼承可使得修改或擴充繼承而來的實作都較為容易。

繼承是有缺點的,那就是父類變,則子類不得不變。繼承會破壞包裝,父類實作細節暴露給子類。繼承顯然是一種類與類之間強耦合的關系。

當兩個類之間具備'is-a'關系時,可以也才考慮繼承。

多态:多态表示沒的對象可以執行相同的動作,但要通過它們自己的實作代碼來執行。

當表現為多态時,

第一,子類以父類的身份出現。(必須定義為父類)

第二,子類在工作時以自己的方式來實作 (通過重寫父類的方法)

第三,子類以父類的身份出現時,子類特有的屬性和方法不可以使用(除了重寫的方法實作外,其它的隻能和父類一樣,子類的特性不可見)

為了使子類的執行個體完全接替來自父類的類成員,父類必須将該成員聲明為虛拟的,這是通過在該成員的傳回類型之前添加virtual關鍵字來實作(其它抽象方法,接口也可以實作多态)

子類可以選擇使用override關鍵字,将父類實作替換為自己的實作。這就是方法重寫 Override.或叫做方法覆寫。

多态的原理是當方法被調用時,無論對象是否被轉換為其父類,都隻有位于對象繼承最末端的方法實作被調用。也就是說,虛方法是按照其運作時類型而非編譯時類型進行動态調用的。

抽象類:

c#允許把類和方法聲明為abstract,即抽象類和抽象方法

抽象類需要注意幾點:

第一,抽象類不能執行個體化

第二,抽象方法是必須被子類重寫的方法

第三,如果類中包含抽象方法,那麼類類必須定義為抽象類,不論是否還包含其它一般方法。

設計抽象類時盡可能讓它擁有多的共同代碼,擁有盡可能少的資料。

抽象類通常代表一個抽象概念,它提供一個繼承的出發點,當設計一個新的抽象類時,一定是用來繼承的,是以,在一個以繼承關系形成的等級結構裡面,樹葉節點應當是具體類,而樹枝節點均應當是抽象類。

接口:interface,接口是把隐式公共方法和屬性組合起來,以封裝特定功能的一個集合。一旦類實作了接口,類就可以支援接口所指定的所有的屬性和成員。聲明接口在文法上與抽象類完全相同,但不允許提供接口中任何成員的執行方式。實作接口的類就類就必須實作接口中的所有的方法和屬性。

一個類可以支援多個接口,多個類也可以支援相同的接口。

接口用interface聲明,而不是class,接口名稱前要加'I',接口中的方法和屬性前面不能有修飾符,方法沒有方法體。(接口的命名,前面要加一個大寫的字母’I‘,這是規範。)

抽象類與接口的差別:

從表象上來說,抽象類可以給出一些成員的實作,而接口不能包含成員的實作。抽象類的抽象成員可以被子類部分實作,接口成員需要全部實作。一個類隻能繼承一個抽象類,但可以實作多個接口。另:

第一,類是對對象的抽象,抽象類是對類的抽象,接口是對行為的抽象。

第二,如果行為跨越不同類的對象,可使用接口,對于一些相似的類對象,用繼承抽象類。(或者可以了解為抽象類是縱向的,而接口是橫向的)

第三,從設計角度來講,抽象類是從子類中發現了公共的東西,泛化出父類,然後子類繼承父類。而接口是根本不知子類的存在,方法如何實作還不确定,預先定義。

接口可以了解為是一組行為的規範的集合,實作它的類都必須嚴格遵守。實作類與接口之間并無明顯的包含或擁有關系。而抽象類與實作類之間是繼承關系。還是'is-a' 的關系。

實作接口與繼承類并不沖突,一個類可以同時繼承類,同時實作接口。

第二部分:oop思想遵循的一些原則與設計思想

程式設計原則一 盡量避免重複代碼;有重複的代碼就要考慮把它抽象出來并封裝之。

面向對象的程式設計,并不是類越多越好,類的劃分是為了封裝,但分類的基礎是抽象,具有相同的屬性功和功能的對象的抽象集合才是類;

面向對象設計其實就是希望做到代碼的責任分解。

對象的繼承關系是在編譯時就定義好了,是以無法在運作時改變從父類繼承的實作,子類的實作與它的父類有非常緊密的依賴關系,以至于父類實作中的任何變化必然會導緻子類發生變化,當你需要複用子類時,如果繼承下來的實作不适合解決新問題,則父類必須重寫或被其它更适合的類替換。這種依賴關系限制了靈活性并最終限制了複用性。

面向對象設計模式展現的就是抽象的思想,類是什麼,類是對對象的抽象,抽象類呢,其實就是對類的抽象,那接口呢,說白了就是對行為的抽象。

---依賴倒轉原則---

依賴倒轉原則:抽象不應該依賴細節,細節應該依賴于抽象。說白了就是要針對接口程式設計,不要對實作程式設計。

高層子產品不應該依賴低層子產品,兩個都應該依賴于抽象。

---裡氏代換原則---

裡氏代換原則:一個軟體實體如果使用的是一個父類的話,那麼一定适用于其子類,而且它察覺不出父類對象和子類對象的差別。也就是說,在軟體裡面,把父類都替換成它的子類,程式的行為沒有變化,簡單地說,子類型必須能夠替換掉它們的父類型。

---依賴倒轉---

依賴倒轉其實可以說是面向對象設計的标志,用哪種語言編寫程式不重要,如果編寫時考慮的都是如何針對抽象程式設計而不是針對細節程式設計,即程式中所有的依賴關系都是終止于抽象類或者接口,那就是面向對象程式設計,反之就是過程化的設計。

---開放-封閉原則---

開放-封閉原則,是說軟體實體(類,子產品,函數等)應該可以擴充,但是不可以修改[ASD];即對擴充開放(Open for extension),對更改封閉(Closed for modification)

面對需求,對程式的改動是通過增加新代碼來進行的,而不是更改現有的代碼,這就是開放-封閉原則的精神所在。

遵循這個原則可以帶來面向對象技術所聲稱的巨大好處,也就是可維護,可擴充,可複用,靈活性好。

---單一職責原則---

單一職責原則(SRP),就一個類而言,應該僅有一個引起它變化的原因;

如果一個類承擔的職責過多,就等于把這些職責耦合在一起,一個職責的變化可能會削弱或者抑制這個類完成其它職責的能力,這種會導緻脆弱的設計,就變化發生時,設計會遭受到意想不到的破壞;

軟體設計真正要做的許多内容,就是發現職責就把那些職責互相分離,如果你能夠想到多于一個的動機去改變一個類,那麼這個類就具有多于一個的職責,就要考慮職責分離;

---迪米特法則---

迪米特法則(LoD),也叫最少知識原則。如果兩個類不必彼此直接通信,那麼這兩個類就不應當發生直接的互相作用。如果其中一個類需要調用另一個類的某一個方法的話,可以通過第三者轉發這個調用。

迪米特法則首先強調的前提是在類的結構設計上,每一個類都應當盡量降低成員的通路權限,也就是說,一個類包裝好自己的private狀态,不需要讓别的類知道的字段或行為就不要公開。

迪米特法則其根本思想是強調了類之間的松耦合。類之間的耦合越弱,越利于複用,一個處在弱耦合的類被修改,不會對有關系的類造成波及。

---合成/聚合複用原則---

合成/聚合複用原則(CARP),盡量使用合成/聚合,盡量不要使用類繼承。

聚合表示一種弱的‘擁有’關系,展現的是A對象可以包含B對象,但B對象不是A對象的一部分;合成則是一種強的‘擁有’關系,展現了嚴格的部分與整體的關系,部分與整體的生命周期一樣。

聚合合成關系圖1:

面向對象程式設計理論知識與思想(oop的思想與原則)

合成/聚合複用原則的好處是,優先使用對象的合成/聚合将有助于你保持每個類被封裝,并被集中在單個任務上,這樣類和類繼承層次會保持較小規模,并且不大可能為不可控制的寵然大物。

附:類的繼承關系結構圖: