330 likes | 462 Views
類別與物件 (PHP4). 類別就是抽象的,而物件就是類別的實體。在這一章我們將介紹物件類別圖來解釋類別。我們在這一章講解 PHP4 中的類別與物件。 在這個物件類別圖中,第一行為物件類別的名子,如訂單、顧客、公司行號、個人客戶、業務代表,第二行為物件類別的屬性 ( 資料成員 ) ,第三行為物件類別的方法 ( 成員函數 ) ,每個類別物件之間都有相互的關係。.
E N D
類別與物件(PHP4) 類別就是抽象的,而物件就是類別的實體。在這一章我們將介紹物件類別圖來解釋類別。我們在這一章講解PHP4中的類別與物件。 在這個物件類別圖中,第一行為物件類別的名子,如訂單、顧客、公司行號、個人客戶、業務代表,第二行為物件類別的屬性(資料成員),第三行為物件類別的方法(成員函數),每個類別物件之間都有相互的關係。
在這一張圖中,顧客是公司行號客戶、和個人客戶的父類別,而行號客戶和個人客戶是顧客的子類別。因為顧客是行號客戶、和個人客戶的一般化,也就是說公司行號客戶、和個人客戶的屬性皆來自顧客的屬性一般化。說簡單一點,我們只要將顧客改一點屬性或方法,他就變成了行號客戶;相同的,我們只要再將顧客改一點屬性或方法,他就變成了個人客戶了。因此,不管行號客戶、和個人客戶,他們都有屬性(名子與電話),也都有方法(評比)。在這一張圖中,顧客是公司行號客戶、和個人客戶的父類別,而行號客戶和個人客戶是顧客的子類別。因為顧客是行號客戶、和個人客戶的一般化,也就是說公司行號客戶、和個人客戶的屬性皆來自顧客的屬性一般化。說簡單一點,我們只要將顧客改一點屬性或方法,他就變成了行號客戶;相同的,我們只要再將顧客改一點屬性或方法,他就變成了個人客戶了。因此,不管行號客戶、和個人客戶,他們都有屬性(名子與電話),也都有方法(評比)。 • 那麼物件就是類別的實體。例如:行號客戶的實體就是第一資訊公司…..;個人客戶實體就是黃大名…..。因此類別就是抽象的,而實體就是實際存在的。 • 物件類別除了繼承外還有多重性的關係。例如一個客戶可以下多張訂單,對於顧客來講,就是一對多的關係(多重性),對於訂單而言則是多對一。對於公司行號對業務代表則是多對一的關係,因為一個業務員需負責多家公司的訂單。 • 將概念轉成物件類別圖後,再撰寫程式開發程式,這樣就方便多了。因為針對不同的使用者,我們設計的物件類別圖也會跟著改變。
1-1類別 • 類別就是將許多抽象的物體集合起來。PHP擁有物件導向的作法,如繼承、封裝和多型。下列是類別繼承的範例。 • 範例class.php • $todays_date、$name、$address、$level稱為customer類別的屬性,而函數credit( )稱為customer類別的方法,而function customer( )稱為類別的建構子,因為他實作了customer類別。我們使用$this來指向customer類別本身。而建構子customer( )則將自己customer類別初始化了。 • 第二行這是顧客類別。 • 第八行這是顧客類別的建構子,讓顧客類別能夠初始化。建構子和類別同名customer。 • 第十七行使用new來實體化類別成為物件,並配置記憶體名為$cu。 • 第二十行顯示顧客類別今天的時間,這個時間已由建構子初始化了(在第九行),就是事先已經建構今天時間了。 • 第二十二行顯示顧客的名稱。
1-2繼承 • 公司行號客戶類別繼承了顧客類別,使用extends字。在公司行號客戶類別繼承了顧客類別的所有屬性與方法。 • 第二十五行公司行號類別(corporate_customer)使用extends來繼承顧客(customer)父類別。Corporate_customer稱為子類別,customer稱為父類別。 • 在第三十二行為企業行號類別配置記憶體,並且將名子取為$cocu。 • 在第三十五行直接顯示繼承來自顧客類別的名子(大大客戶與小小客戶),而在第三十七行作修改。第三十七行Overloaded覆蓋屬性名子,修改名子為第一資訊公司。 • 在第四十行顯示企業行號客戶的訂單時間。 • 在第四十三行設定企業行號客戶的評比。
顯示第三十五行企業行號客戶類別繼承來自顧客類別的名子(大大客戶和小小客戶)。顯示第三十五行企業行號客戶類別繼承來自顧客類別的名子(大大客戶和小小客戶)。 • 顯示第三十七行修改企業行號類別的名子(第一資訊公司)。 • 顯示在第四十行顯示企業行號客戶的訂單時間(December 31,20047:51 am)。 • 顯示第四十三行企業公司行號類別的評比(a)。
第四十七行個人客戶類別(personal_customer)是繼承自顧客類別(customer)。第四十七行個人客戶類別(personal_customer)是繼承自顧客類別(customer)。 • 第五十一行call( )這是個人客戶類別的成員函數。 • 第五十五行使用new來實體化類別成為物件,並配置記憶體名為$cu。 • 第六十行顯示個人客戶的名子,黃大名。 • 第六十六行設定個人客戶的等級”b”,第六十七行顯示個人客戶的等級”b”。
這是顯示的情況。 • 顯示第五十八行繼承自客戶父類別的名稱(大大客戶和小小客戶)。 • 顯示第六十一行的個人客戶名稱(黃大名)。 • 呼叫第六十四行的call( )這是個人客戶類別的成員函數,並且在第六十五行顯示電話號碼。 • 第六十六行設定個人客戶的評比”b”,並第六十七行顯示評比”b”。
1-3參考內部的建構子 • 在unix中我們使用ln(hardlink)來連接檔案,ln連接並不會影響檔案內容,他只是建立另外一個檔案名稱而已(請看補充---硬連結)。這就和參考一樣,我們使用參考來建立另外一個檔案名稱,而不會改變到原來檔案的內容。a參考c和b參考c,他們都指向同一個檔案c,而a、b只是檔案的名子,c確有實質內容。但php的參考卻和c的指標不同。
範例re2.php • 在re2.php中第三行和第四行為變數$c的參考,當變數$c(被參考值)改變時,a和b都也會改變。 • 在第十二行和第十三行變數$e和變數$f複製了變數$d,把所有的內容都複製進來。所以,當變數$d改變時,變數$e和變數$f都不會變化。
第三行和第四行為變數$c的參考,當變數$c(被參考值)改變時,a和b都也會改變。因此,變數$c由5改變成6。第三行和第四行為變數$c的參考,當變數$c(被參考值)改變時,a和b都也會改變。因此,變數$c由5改變成6。 • 在第十二行和第十三行變數$e和變數$f複製了變數$d,把所有的內容都複製進來。所以,當變數$d改變時,變數$e和變數$f都不會變化,還是3。
範例re1.php • 在建構子內使用參考 • 我們在foo類別中建立了foo建構子,並讓一個全域變數參考他。 • 第六行在全域變數內建立建構子。
第二十二行、第二十三行和第二十五行皆會顯示哈哈。第二十二行、第二十三行和第二十五行皆會顯示哈哈。 • 第二十八行和第三十一行都修改foo物件的名子,但只有複製參考才能完全改變foo的內容。 • 第三十一行因為第二十一行並未將類別本身建構子給參考到,所以第二十九行顯示阿阿而第三十一行顯示哈哈。 • 第二十四行將類別foo的建構子也參考到了,所以第三十一行和第三十二行都顯示阿阿。
1-4建構子 • 建構子是當我們使用new來新增類別實體時自動會執行該函數。在PHP3時,當函數和他的類別名稱相同時,這就是PHP3的建構子。在PHP4中,當在類別內定義相同名稱的函數,則這函數就被稱為建構子。 • 範例:c1.php • 第二行到第六行為類別A的定義。 • 第三行到第五行為類別A的建構函數。 • 第八到第十二行為類別A的子類別B,類別B繼承了類別A。 • 在PHP3中,第十四行新增物件b,沒有建構子會被呼叫,但在PHP4中則會被呼叫.。PHP4中如果該類別沒有建構子,則會去呼叫上一層的建構子。
PHP4中如果該類別沒有建構子,則會去呼叫上一層的建構子。因此,在PHP4中,它顯示了上一層建構子。PHP4中如果該類別沒有建構子,則會去呼叫上一層的建構子。因此,在PHP4中,它顯示了上一層建構子。
範例:c2.php • 第二行到第十四行為類別A的定義。 • 第四行到第七行為類別A的建構子。 • 第十六行到第二十二行為類別A的子類別B的定義。 • 第二十五行新增物件B。因為類別B中的第十六行到第二十二行找不到類別B的建構子,因此往上一層父類別A中來尋找,因此會執行第九行到第十三行。
第二十五行新增物件B。因為類別B中的第十六行到第二十二行找不到類別B的建構子,因此往上一層父類別A中來尋找,因此會執行第九行到第十三行,而顯示這個內容。第二十五行新增物件B。因為類別B中的第十六行到第二十二行找不到類別B的建構子,因此往上一層父類別A中來尋找,因此會執行第九行到第十三行,而顯示這個內容。
1-5範圍解析運算子 • 有時後參考還未物件化類別內的函數或物件,我們可以使用範圍運算子scope::。 • Scope.php這個範例,會呼叫類別A的函數example,但是並沒有將類別A給實體化。因為我們沒有將物件實體化,因此我們不能寫成$a->example()。有類別函數,但是沒有類別變數。實際上,在呼叫時並沒有物件,因此類別函數將不會用到任何物件變數和$this,但是它可以使用區域變數或全域變數。 • 在這個範例中class B重新導向到example函數,因此類別A的example將沒有作用。除非我們使用範圍運算子::來實作A類別的example函數。 • 範例:scope.php • 第二行到第七行我們定義類別A。 • 第八行到第十三行定義類別A的子類別B,並且在第九行到第十二行重新導向到新的example()函數。 • 第十五行我們使用A::example()範圍運算子來實作類別A的example()函數。 • 第十七行我們新增類別B的物件$b。 • 第二十行呼叫物件$b的example函數。
第十五行我們使用A::example()範圍運算子來實作類別A的example()函數,因此顯示A::example()。第十五行我們使用A::example()範圍運算子來實作類別A的example()函數,因此顯示A::example()。 • 第十七行我們新增類別B的物件$b,第二十行呼叫物件$b的example函數, • 因此顯示B::example和A::example。
1-6parent父類別 • 我們寫程式時會參考到我們基礎類別(父類別)的函數和變數。我們使用parent這個關鍵字來參考(基礎類別)父類別。範例parent.php中,我們使用parent::example()來實作類別B的父類別A的example函數。 • 範例:parent.php • 我們使用parent::example()來實作類別B的父類別A的example函數。 • 第十一行使用parent::example()在類別B中實作父類別A的example函數。 • 第十四行新增類別B的物件$b。
首先執行類別B的example()函數,再用parent::example()執行類別A的example函數。首先執行類別B的example()函數,再用parent::example()執行類別A的example函數。
1-7建構子內的參考 • 在建構子內建立參考不是很好的程式寫法,要盡量避免這個錯誤。 • 範例:rci.php • 在第十六行使用複製運算子=,來建立$bar1這個物件。 • 在第十九行使用參考運算子=&,來建立$bar2這個物件。 • $bar1和$globalref[0]不是被參考的,它們不是相同的變數,因為new這個關鍵字預設是回傳複製,而不是回傳參考。
1-8比較物件 • 在PHP4中物件比較是很容易的,假如兩個物件有相同的屬性和值,則這兩個物件是辨識相同的,而且是相同類別的實體物件。我們可以使用===辨識運算子來比較兩個物件。當物件從相同的類別實作,而且屬性有相同的值時,這時物件為辨識相同。===為辨識運算子,$a === $b,假如$a和$b為相等,而且它們有相同的類型則為真。 • 範例:compare_object.php • 第二行到第七行我們定義了bool2str()函數,當$bool為真時則回傳true,當$bool為假時則回傳false。 • 第九行到第十四行是定義比較物件函數compareObjects(&$o1,&$o2);我們使用&參考運算子來將物件的位址帶入。 • 第十五行到第二十行是定義Flag類別。 • 第二十二行到第二十九行是定義Flasg的子類別switchableflag類別。 • 第三十行是新增Flag類別的物件$o。 • 第三十一行是新增Flag類別,並且將參數False帶入,來新增物件$p。 • 第三十二行是新增Flag類別的物件$q。 • 第三十三行是新增switchableflag類別(flag子類別)的物件$r。 • 第三十五行執行比較物件compareobject(&$o,&$q),因為$o和$q物件相同。 • 第三十八行執行比較物件compareobject(&$o,&$p),因為$o物件和$p物件所帶入的參數不同,所以物件不相等。 • 第四十一行執行比較物件compareobject(&$o,&$r),因為$o物件為$r物件的父類別的物件,所以不相等。
===辨別運算子能夠辨別兩個物件是否為相同類型,而且屬性是否有相同的值。===辨別運算子能夠辨別兩個物件是否為相同類型,而且屬性是否有相同的值。 • 第一個是執行比較物件compareobject(&$o,&$q),因為$o和$q物件相同,它們都是相同的類別且帶入的參數相同。 • 第二個是執行比較物件compareobject(&$o,&$p),因為$o物件和$p物件所帶入類別的參數不同,所以實作物件不相等。 • 第三個執行比較物件compareobject(&$o,&$r),因為$o物件為$r物件的父類別的物件,所以不相等。