參考資料:《程式語言教學誌》PHP類別與物件


PHP 快速導覽 - const 常數 

類別 (class) 中可以使用關鍵字 (keyword) const 定義常數 (constant) ,常數的識別字 (identifier) 不需要加上金錢符號 $ ,舉例如下
 
<?php
class Demo {
    const c = "constant value\n";
     
    function do_something() {
        return self::c;
    }
}
 
echo Demo::c;
$d = "Demo";
echo $d::c;
$o = new Demo();
echo $o::c;
echo $o->do_something();
 
?>
 

PHP 快速導覽 - 建構子與解構子

建構子 (constructor) 為建立物件 (object) 時所執行的方法 (method) ,解構子 (destructor) 則是物件不再使用後執行的方法。

舉例如下
 
<?php
class Demo {
    function __construct() {
        echo "constructor call...\n";
    }
     
    function __destruct() {
        echo "destructor call...\n";
    }
     
    function do_something() {
        echo "do something\n";
    }
}
 
$o = new Demo();
$o->do_something();
 
?>
 

PHP 快速導覽 - 內建方法

除了建構子 (constructor) 與解構子 (destructor) 外,類別 (class) 還有些預設的內建方法 (method) ,如果沒有實際需求並不需要改寫這些方法。

方法說明
__call($name, $arguments) 當呼叫不存在的方法時執行
__callStatic($name, $arguments) 當呼叫不存在的 static 方法時執行
__get($name) 當讀取不存在的屬性時執行
__set($name, $value) 當設定不存在的屬性時執行
__isset($name) 當使用不存在的屬性呼叫 isset() 或 empty() 時執行
__unset($name) 當使用不存在的屬性呼叫 unset() 時執行
__sleep() 在物件序列化之前執行
__wakeup() 在物件序列化過程中重建物件
__toString() 物件的字串形式
__invoke($x) 當把物件當函數呼叫時執行
__set_state($an_array) 當呼叫 var_export() 方法時執行
__clone() 使用 clone 複製物件完成後執行

 

舉一例如下

<?php
class Demo {
    public function __call($name, $arguments) {
        echo "something wrong";
    }
}
 
$d = new Demo();
$d->do_something();
 
?>
 

PHP 快速導覽 - 繼承

繼承 (inheritance) 為物件導向程式設計 (object-oriented programming) 的特性之一,子類別 (subclass) 可以承接父類別 (superclass) 的 public 或 protected 成員 (member) ,使之具有共通的 public 或 protected 成員。

舉例如下
<?php
class Demo {
    private $a = "superclass_a";
    protected $b = "superclass_b";
    public $c = "superclass_c";
     
    function do_something() {
        echo "a: $this->a, b: $this->b, c: $this->c\n";
    }
}
 
class Demo2 extends Demo {
    function do_something() {
        echo "a: $this->a, b: $this->b, c: $this->c\n";
    }
}
 
$o = new Demo2();
$o->do_something();
 
?>
 

PHP 快速導覽 - static 成員

類別 (class) 中的 static 成員 (member) 屬於類別,這是說不需要建立物件 (object) 實體就可使用 static 成員。

舉例如下
 
<?php
class Demo {
    public static $zero = 0;
     
    public static function do_something() {
        return self::$zero;
    }
}
 
echo Demo::$zero . "\n";
echo Demo::do_something() . "\n";
$d = new Demo();
echo $d->zero . "\n";
echo $d->do_something();
 
?>
 

PHP 快速導覽 - abstract 類別與方法

 
類別 (class) 可以把方法 (method) 宣告成 abstract ,有 abstract 方法的類別也要宣告為 abstract , abstract 方法只需要宣告方法名稱與參數列 (parameter list) ,至於方法的實作則留給繼承的子類別 (subclass) 。

舉例如下
 
<?php
abstract class Demo {
    abstract protected function do_something();
     
    function do_something2() {
        echo "hi\n";
    }
}
 
class Demo2 extends Demo {
    function do_something() {
        echo "hello\n";
    }
}
 
$d = new Demo2();
$d->do_something();
$d->do_something2();

?>
 

PHP 快速導覽 - final 類別與方法

 
使用 final 宣告的類別 (class) 不能被繼承,同樣的,使用 final 宣告的方法 (method) 不能被子類別 (subclass) 改寫。
 
舉例如下
 
<?php
class Demo {
    public function do_something() {
        echo "1\n";
    }
    
    final public function do_something2() {
        echo "2\n";
    }
}
 
class Demo2 extends Demo {
    public function do_something2() {
        echo "3\n";
    }
}
 
$d = new Demo2();
$d->do_something();
$d->do_something2();
 
?>
 

Demo2 繼承自 Demo ,若執行 do_something2() 會發生錯誤

final 類別則不能被繼承,例如

<?php
final class Demo3 {
   public function do_something() {
       echo "1\n";
   }
}
 
class Demo4 extends Demo3 {}
 
$d = new Demo4();
$d->do_something();
 
?>
 

用 Demo4 繼承 Demo3 同樣會發生錯誤


PHP 快速導覽 - 介面

 
介面 (interface) 是一種可定義常數屬性的 abstract 類別 (class) ,主要用為定義程式的共通規格,利用關鍵字 (keyword) interface 宣告,類別用 implements 實作。

舉例如下
 
<?php
interface Demo {
    const n = 100;
    public function do_something();
}
 
class Demo2 implements Demo {
    function do_something() {
        return self::n;
    }
}
 
$d = new Demo2();
echo Demo::n . "\n";
echo $d->do_something();
 
?>
 

一個類別可以實作多個介面,此時在 implements 後面以逗號分隔介面識別字 (identifier) 即可,例如

<?php
interface Demo3 {
    public function do_something1();
}
 
interface Demo4 {
    public function do_something2();
}
 
class Demo5 implements Demo3, Demo4 {
    function do_something1() {
        return "Demo3";
    }
     
    function do_something2() {
        return "Demo4";
    }
}
 
$d2 = new Demo5();
echo $d2->do_something1() . "\n";
echo $d2->do_something2();
 
?>
 

PHP 快速導覽 - 介面的繼承

介面 (interface) 可藉由 extends 繼承其他介面擴充規格,就像類別 (class) 可實作多個介面一樣,介面的繼承可以是多重的,也就是一個介面可以同時繼承多個介面。 

舉例如下

<?php
interface Demo {
    public function do_something1();
}
 
interface Demo2 {
    public function do_something2();
}
 
interface Demo3 extends Demo, Demo2 {
    public function do_something3();
}
 
class Demo4 implements Demo3 {
    function do_something1() {
        return "1";
    }
     
    function do_something2() {
        return "2";
    }
     
    function do_something3() {
        return "3";
    }
}
 
$d2 = new Demo4();
echo $d2->do_something1() . "\n";
echo $d2->do_something2() . "\n";
echo $d2->do_something3();
 
?>
 

PHP 快速導覽 - Trait 機制之基礎應用

特徵機制 (trait) 屬於特別的類別 (class) 與介面 (interface) 的融合體,利於程式碼的重複使用,像類別的地方在於可定義屬性 (property) 與方法 (method) ,像介面的地方在於不能建立物件 (object) 與可使用多個特徵機制。
舉例如下
 
<?php
trait Demo {
    public $a = 22;
     
    public function do_something() {
        echo "hello";
    }
}
 
class Demo2 {
    use Demo;
}
 
$d = new Demo2();
echo $d->a . "\n";
echo $d->do_something();
 
?>

特徵機制使用關鍵字 trait 定義
之後使用該特徵機制 Demo 的類別,利用 use 便可重複利用 Demo 定義好的屬性與方法

也像類別可實作多個介面一樣,單一類別可 use 多個特徵機制,若是數個特徵機制中有相同名稱的方法,就須額外指定用哪個特徵機制中的方法,例如

<?php
trait Demo3 {
    publicfunctiondo_something() {
        echo"hello";
    }
}
trait Demo4 {
    publicfunctiondo_something() {
        echo"yes";
    }
}
classDemo5 {
    useDemo3, Demo4 {
        Demo3::do_something insteadof Demo4;
    }
}
$d= newDemo5();
echo$d->do_something();
 
?>

特徵機制使用關鍵字 trait 定義
之後使用該特徵機制 Demo 的類別,利用 use 便可重複利用 Demo 定義好的屬性與方法


PHP 快速導覽 - Trait 機制之更改權限

使用特徵機制 (trait) 的類別 (class) 可更改方法 (method) 的權限,也可替方法取別名 (alias) 。

<?php

trait HelloWorld {

    public function sayHello() {
        echo 'Hello World!';
    }
}
 
class Demo1 {
    use HelloWorld {
        sayHello as protected;
    }
}
 
$d1 = new Demo1();
echo $d1->sayHello();
 
?>

use 後利用大括弧,然後利用關鍵字 as 更改權限,由於 sayHello 被改成 protected ,因此執行會發生錯誤訊息。

另外可在權限關鍵字之後加上別名,例如

<?php
trait HelloWorld {
    public function sayHello() {
        echo 'Hello World!';
    }
}
 
class Demo2 {
    use HelloWorld {
        sayHello as private myPrivateHello;
    }
}
 
$d2 = new Demo2();
echo $d2->sayHello();
 
?>
 
此例 myPrivateHello() 為 private 的方法,而 sayHello() 的權限不變,仍是 public 的方法。
 

PHP 快速導覽 - Trait 機制之複合使用

 
特徵機制 (trait) 的亦可 use 其他的特徵機制,這是說特徵機制的組成可以是多個不同的特徵機制。
 
舉例如下
 
<?php
trait Demo1 {
    public function do_something1() {
        echo '1';
    }
}
 
trait Demo2 {
    public function do_something2() {
        echo '2';
    }
}
 
trait Demo3 {
    use Demo1, Demo2;
}
 
class Demo4 {
    use Demo3;
}
 
$d = new Demo4();
echo $d->do_something1() . "\n";
echo $d->do_something2() . "\n";
 
?>
 
此例的 Demo3 由 Demo1 與 Demo2 組成
 

PHP 快速導覽 - 迭代器

物件 (object) 也可以當迭代器 (iterator) 使用,這是說可以用 foreach 迴圈 (loop) 逐一取得每一個屬性 (property) 。

舉一例如下
 
<?php
class Demo {
    public $a = 10;
    public $b = 11;
    public $c = 12;
     
    public function do_something() {
        foreach($this as $key => $value) {
            echo "$key => $value\n";
        }
    }
}
 
$d = new Demo();
$d->do_something();
echo "\n";
 
foreach($d as $key => $value) {
    echo "$key => $value\n";
}
 
?>
 
基本上屬性就是 key-value 配對的陣列 (array) , do_something() 方法 (method) 使用 foreach 迴圈印出所有屬性值
 

PHP 快速導覽 - clone 複製物件

關鍵字 (keyword) clone 可以將物件 (object) 複製給另一個變數 (variable) ,此會執行內建的 __clone() 方法 (method) 。 

舉例如下
 
<?php
class Demo {
    static $counter = 0;
     
    public function __clone() {
        echo "grow as a clone...\n";
        self::$counter++;
    }
}
 
$a = new Demo();
$b = clone $a;
$c = clone $a;
$d = clone $b;
$e = clone $c;
echo Demo::$counter;
 
?>
 
此例中我們改寫 __clone() 方法,並且以 $counter 紀錄 clone 的使用紀錄