理解組合對象與類繼承


  

1.概念解析

  • 繼承:"繼承"是面向對象編程中的一個概念。

    面向對象編程的單一職責原理(SPR-Single Responsibility Principle)規定對象只能有一個職責。就一個類而言,應該僅有一個引起它變化的原因。 為什么要把不同的職責分配到不同的類中呢?因為每一個職責都是變化的一個軸線,當需求變化時,該變化會反映為類的職責的變化。如果一個類承擔了多於一個的職責,那么就意味着引起它的變化的原因會有多個。如果一個類承擔的職責過多,那么就等同於把這些職責耦合在了一起。一個職責的變化可能會抑制到該類完成其他職責的能力,這樣的耦合會導致脆弱的設計。當變化發生時,設計會受到意想不到的破壞。

    這個原則的核心含意是:一個類應該有且僅有一個職責。關於職責的含意,面向對象大師Robert.C.Martin有一個著名的定義:所謂一個類的職責是指引起該類變化的原因,如果一個類具有一個以上的職責,那么就會有多個不同的原因引起該類變化,其實就是耦合了多個互不相關的職責,就會降低這個類的內聚性

    例如我們現在有兩個類,D和C。那么類D的對象可以使用僅對類C對象有效的方法或屬性,它使得這些方法和屬性就像是由D定義的。這時,C是D的父類,D是C的子類。由於在繼承過程中,父類的內部細節對子類完全可見,因此通過繼承的代碼復用被稱為“白盒式代碼復用”(white-box reuse)。

    因此,當你通過從另一個對象繼承的方式來創建一個新的對象時,目標就應該是使得新的對象有一個相對於原始對象更加特定的版本。

  • 對象組合(組合對象):將多個元素作為一個對象來處理,需要將它們組合。

    一個對象可以把對象作為自己的成員變量,如果用這樣的類創建對象,那么該對象中就會有其它對象,也就是說該對象將其他對象作為自己的組成部分(這就是人們常說的Has-A),或者說該對象是由幾個對象組合而成。

    對象組合就是通過對現有的對象進行拼裝(組合)產生新的、更復雜的功能,而由於對象之間各自內部細節不對外可見,所以這種方式的代碼復用被稱為“黑盒式代碼復用”(black-box reuse)。對象組合要求被組合的對象具有良好定義的接口。

  舉例:

<?php

class person{

  public $name;

  public $gender;

  public function say(){

    echo $this->name," \tis ",$this->gender,"\r\n";

  }

}

class family{

  public $people;

  public $location;

  public function construct($p,$loc){

    $this->people=$p;

    $this->location=$loc;

  }

}

$student=new person();

$student->name='Tom';

$student->gender='male';

$student->say();

$tom=new family($student,'peking');

 

  以上代碼中,定義了兩個類,一個是person,一個是family;在family類中創建person類中的對象,把這個對象視為family類的一個屬性,並調用它的方法處理問題,這種復用方式就叫“組合”。

 

2、繼承與組合區別

  類繼承是在編譯時刻靜態定義的,且可直接使用,因為程序設計語言直接支持類繼承。類繼承可以較方便地改變被復用的實現。當一個子類重定義一些而不是全部操作時,它也能影響它所繼承的操作,只要在這些操作中調用了被重定義的操作。
  但是類繼承也有一些不足之處。首先,因為繼承在編譯時刻就定義了,所以無法在運行時刻改變從父類繼承的實現。更糟的是,父類通常至少定義了部分子類的具體表示。因為繼承對子類揭示了其父類的實現細節,所以繼承常被認為“破壞了封裝性” 。子類中的實現與它的父類有如此緊密的依賴關系,以至於父類實現中的任何變化必然會導致子類發生變化。當你需要復用子類時,實現上的依賴性就會產生一些問題。如果繼承下來的實現不適合解決新的問題,則父類必須重寫或被其他更適合的類替換。這種依賴關系限制了靈活性並最終限制了復用性。一個可用的解決方法就是只繼承抽象類,因為抽象類通常提供較少的實現。

 對象組合是通過獲得對其他對象的引用而在運行時刻動態定義的。組合要求對象遵守彼此的接口約定,進而要求更仔細地定義接口,而這些接口並不妨礙你將一個對象和其他對象一起使用。這還會產生良好的結果:因為對象只能通過接口訪問,所以我們並不破壞封裝性;只要類型一致,運行時刻還可以用一個對象來替代另一個對象;更進一步,因為對象的實現是基於接口寫的,所以實現上存在較少的依賴關系

  對象組合對系統設計還有另一個作用,即優先使用對象組合有助於你保持每個類被封裝,並被集中在單個任務上。這樣類和類繼承層次會保持較小規模,並且不太可能增長為不可控制的龐然大物。另一方面,基於對象組合的設計會有更多的對象 (而有較少的類),且系統的行為將依賴於對象間的關系而不是被定義在某個類中
  這導出了我們的面向對象設計的第二個原則:優先使用對象組合,而不是類繼承

 

推薦閱讀》》

面向對象編程中的繼承和組合的簡單比較

面向對象的編程概念:組合(Composition)和聚合(aggregation)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM