這部分要繼續介紹下半章~
主要會分為:
- 多載
- 物件的複製與比較
- 型別約束
- 後期靜態綁定
- 物件的引用
- 序列化
下半章相對簡單一點
雖然其中一些可能不常會使用到
但相對的,也有非常重要的概念在裡頭~
事不宜遲,就馬上開始介紹吧!
1. 多載
第一章要先來介紹 PHP 的多載
在其他語言中的多載會像是使用同一個函式名稱,然後用不同的參數或回傳型態去區別各種方法~
但是!!!在 PHP 的多載並不是這樣
在 PHP 裡多載的定義會是動態去建立屬性或方法
通過定義 magic method (魔術方法) 去實現 PHP 定義的多載
這裡先額外說明一下什麼是魔術方法
就是一系列以 __ 開頭的方法名稱,它們會在特定的時機被呼叫
例如 __construct() 就是建構元,會在建立物件的時候被呼叫~
還有一點要特別注意的就是多載的參數都不可以以傳參考的方式傳入!!!
只能以普通傳值的方式將參數傳到魔術方法裡
而在 PHP 當中的多載有分為兩種,分別是屬性多載和方法多載
區別在於試圖呼叫不存在的屬性還是方法,就對應屬性多載或是方法多載~
下面就依序來介紹屬性多載以及方法多載
1. 屬性多載
屬性多載有以下 4 種對應的方法
set(string $name, mixed $value)
當試圖在物件裡面寫入不存在的屬性的時候,就會呼叫 set 這個魔術方法get(string $name)
當試圖在物件裡面讀取不存在的屬性的時候,就會呼叫 get 這個魔術方法__isset(string $name)
如果我們對某個物件使用 isset() 或是 empty() 方法作判斷時,則會觸發這個魔術方法__unset(string $name)
當我們針對某物件作 unset() 時,會觸發這個魔術方法
當我們試圖對物件執行上面的 4 種操作時,就必需要先在類別當中定義對應的魔術方法,達到多載的效果
如此一來,操作才會被正常的執行,反之則會因為呼叫不存在的屬性而發生錯誤!
可以視需求在類別中定義這些魔術方法~
1 | class BaseClass{ |
2. 方法多載
而方法多載有以下 2 種對應的方法,分別是
call(string $name, array $arguments)
當試圖呼叫不存在類別中的方法時,會觸發 call 魔術方法callStatic(string $name, array $arguments)
和 call 魔術方法的差異在於,當試圖呼叫不存在類別中的靜態方法時,則會觸發 callStatic 而非 call
1 | class BaseClass{ |
2. 物件的複製與比較
這個章節我把物件的複製和比較放在一起介紹
但其實在實做上並不會很常用到這兩種~~
不過物件的複製也算是 PHP 的一個特色 (我自己認為 XD
所以還是稍為帶到一下~
複製
主要是使用 clone 這個關鍵字進行物件的複製
可以複製另外一個相同的物件出來
另外在 PHP 當中,也有提供 clone 這個魔術方法
當我們使用 clone 這個關鍵字的時候,就會觸發 clone 這個魔術方法~
一樣也可以通過覆寫 __clone 來客製化物件複製的函式內容
1 | class testClass { |
比較
而比較的部分就相對簡單許多
可以使用 == 或是 === 來比較兩個物件是否相同
而兩者的差異在於
當使用 == 時,僅會比較兩個物件的數值是否相同
而當使用 === ,不只會比較數值,還同時會比較型態是否相同
一般可能常見於比較物件是否等於 false
這時候就可以使用 === 來確保判斷正確~
1 | class testClass { |
3. 型別約束
在一般撰寫 C++、C#… 等語言的時候,我們都必需要在函式的參數加上參數的型態
例如 string or float…等等
這個代表傳進來的參數必需要符合這個型態
而根據不同型態或參數的個數也就成為了其他語言的多載~
但是 PHP 在正常的情況下是不需要作型態的指定的
原因是因為 PHP 會在實際使用到變數的時候才辨識變數的型態
所以可以在不指定型態的情況下自由運用變數
是非常方便使用的一個機制!
不過反過來說
在不指定型態的情況下,也代表著無法確認變數的型態
就需要在使用變數之前先作判斷,避免變數的型態不符合預期而發生錯誤!
這同樣適用於函適的參數~
因此在 PHP 5 裡面加入了一個型別約束的機制,讓 PHP 可以像其他語言一樣,對參數進行型別的約束
特別要注意的是:
- 型別約束只針對函式的參數
- 型別約束不可以用在外部 resource 或是純量上 (如 stringin、float)
上面的說明只是為了解釋型別約束的用意而已
實際運用是不可以用在純量上的!
可以用來約束特定的類別
限定傳入特定的類別進行操作!
在宣告函式的時候,可以在參數的前面加上型態
這時候傳遞的參數就必須符合函式的型態,才可以正常執行~
1 | class baseClass { |
4. 後期靜態綁定
這是 PHP 在撰寫類別的一個非常重要的小細節!!!
後期靜態綁定和前期靜態綁定是兩個成對的概念,並且都常常會使用到!
兩者的區別在於呼叫類別的方法時,會分別去使用哪個類別裡面定義的方法
換句話來說就是當某個子類別繼承父類別的同時又去改寫的父類別定義的某個方法時
可以透過這兩種方法去區分現在要執行的是原定義的方法,還是改寫後的方法~
透過下面的描述應該可以幫助了解這個概念
前期靜態綁定
當使用 self:: 這個關鍵字時,就代表前期靜態綁定
只要使用 後面接上的方法時,只會呼叫自己類別裡定義的對應方法
就算這個方法被子類別所改寫,仍然後呼叫自己定義的方法。
1 | class A { |
後期靜態綁定
而後期靜態綁定則是在呼叫方法的時候先去找自己類別有沒有改寫後的方法
若沒有才會使用父類別裡面定義的方法
可以使用的關鍵字有兩種
分別是 static:: 和 $this->
這兩種都可以代表後期靜態綁定
差別在於 static 適用於靜態方法,而 $this 適用於一般方法
1 | class A { |
5. 物件的引用
這部分要提到一個 PHP 物件的重要概念
就是在 PHP 當中要使用物件時,實際上是取用物件的一個辨識,而非物件本身
不管是使用傳值、傳參考或是函式回傳的方式,實際上都是去複製物件的辨識
所以後續的任何操作其實都是在操作同一個物件!
這和之前提到的變數是不一樣的,所以特別提一下~
下面使用一般賦值的方式作一個示範1
2
3
4
5
6
7
8class testClass {
public $val = 1;
}
$testA = new testClass();
$testB = $testA;
$testB->val = 2;
echo $testA->val; // 結果會印出 2
6. 序列化
在 PHP 當中有提供將物件序列化以及反序列化的方法
分別是 serizlize() 和 unserizlize()
可以將類別轉化為字串,方便傳遞到其他檔案裡進行實做
在一般的情況下,我們可能更常聽過 JSON
而 PHP 當中也有提供 json_encode() 和 json_decode() 的方法
也同樣是輕量化的資料傳輸格式
但最大的區別在於
PHP 自己提供的序列化方法是適用於 PHP 的 (有點怪的邏輯
而 JSON 比較像是適用於多種的語言
而這些造成的差異就是
我們可以將一個定義好的類別用 PHP 提供的序列化方法進行序列化
傳到其他檔案再反序列化之後,仍然可以將這個定義好的類別進行實做 (也就是 new 出來)
這是和 JSON 不一樣的地方~
不過其實我也沒有使用過~
根據官方的描述,應該是適用於 session 在儲存的時候吧!
下方就附上一個官方文檔的範例來說明~
1 | // classa.inc: |