iT邦幫忙

2021 iThome 鐵人賽

DAY 15
0
自我挑戰組

後端新手PHP+Laravel筆記系列 第 15

[Day15]PHP Class 類別02

PHP Class 類別

1. class屬性

類的變量成員叫做“屬性”,或者叫“字段”、“特徵”,在PHP文檔統一稱為“屬性”。屬性聲明是由關鍵字 public(公開),protected(非公開) 或者 private(私有) 開頭,然後跟一個普通的變量聲明來組成。屬性中的變量可以初始化,但是初始化的值必須是常數,這裡的常數是指 PHP 腳本在編譯階段時就可以得到其值,而不依賴於運行時的信息才能求值。

在類的成員方法裡面,可以用 ->(對象運算符):$this->property(其中 property 是該屬性名)這種方式來訪問非靜態屬性。

靜態屬性則是用 ::(雙冒號):self::$property 來訪問。

以下為屬性聲明範例

<?php
class SimpleClass
{
   // 錯誤的屬性聲明
   public $var1 = 'hello ' . 'world';
   public $var2 = <<<EOD
hello world
EOD;
   public $var3 = 1+2;
   public $var4 = self::myStaticMethod();
   public $var5 = $myVar;

   // 正確的屬性聲明
   public $var6 = myConstant;
   public $var7 = array(true, false);

   //在 PHP 5.3.0 及之後,下面的聲明也正確
   public $var8 = <<<'EOD'
hello world
EOD;
}
?>

1. 類常量

可以把在類中始終保持不變的值定義為常量。在定義和使用常量的時候不需要使用 $ 符號。 常量的值必須是一個定值,不能是變量,類屬性,數學運算的結果或函數調用。

如何定義和使用類常量,查看以下範例

<?php
class MyClass
{
    const constant = 'constant value';

    function showConstant() {
        echo  self::constant . "\n";
    }
}

echo MyClass::constant . "\n";

$classname = "MyClass";
echo $classname::constant . "\n"; // 自 5.3.0 起

$class = new MyClass();
$class->showConstant();

echo $class::constant."\n"; // 自 PHP 5.3.0 起
?>

3. 類的自動加載

在編寫有關於對象(OOP) 程序時,很多開發者為每個類新建一個 PHP 文件。這會帶來一個煩惱:每個腳本的開頭,都需要包含(include)一個長長的列表(每個類都有個文件)。

在 PHP 5 中,已經不再需要這樣了。 spl_autoload_register() 函數可以註冊任意數量的自動加載器,當使用尚未被定義的類(class)和接口(interface)時自動去加載。通過註冊自動加載器,腳本引擎在 PHP 出錯失敗前有了最後一個機會加載所需的類。

儘管 __autoload() 函數也能自動加載類和接口,但更建議使用 spl_autoload_register() 函數。 spl_autoload_register() 提供了一種更加靈活的方式來實現類的自動加載(同一個應用中,可以支持任意數量的加載器,比如第三方庫中的)。因此,不再建議使用 __autoload() 函數,在以後的版本中它可能被棄用

1. 自動加載範例

本例嘗試分別從 MyClass1.php 和 MyClass2.php 文件中加載 MyClass1 和 MyClass2 類。

<?php
spl_autoload_register(function ($class_name) {
    require_once $class_name . '.php';
});

$obj  = new MyClass1();
$obj2 = new MyClass2();
?>
2. 自動加載在 PHP 5.3.0+ 中的異常處理
<?php
spl_autoload_register(function ($name) {
    echo "Want to load $name.\n";
    throw new Exception("Unable to load $name.");
});

try {
    $obj = new NonLoadableClass();
} catch (Exception $e) {
    echo $e->getMessage(), "\n";
}
?>

// Want to load NonLoadableClass.
// Unable to load NonLoadableClass.

4. 構造函數和析構函數

構造函數

__construct(mixed ...$values = ""): void

PHP 允許開發者在一個類中定義一個方法作為構造函數。具有構造函數的類會在每次創建新對象時先調用此方法,所以非常適合在使用對象之前做一些初始化工作

注意: 如果子類中定義了構造函數則不會隱式調用其父類的構造函數。要執行父類的構造函數,需要在子類的構造函數中調用 parent::__construct()。如果子類沒有定義構造函數則會如同一個普通的類方法一樣從父類繼承(假如沒有被定義為 private 的話)。

1. 繼承中的構造函數
<?php
class BaseClass {
    function __construct() {
        print "In BaseClass constructor\n";
    }
}

class SubClass extends BaseClass {
    function __construct() {
        parent::__construct();
        print "In SubClass constructor\n";
    }
}

class OtherSubClass extends BaseClass {
    // 繼承 BaseClass 的構造函數
}

// In BaseClass constructor
$obj = new BaseClass();

// In BaseClass constructor
// In SubClass constructor
$obj = new SubClass();

// In BaseClass constructor
$obj = new OtherSubClass();
?>
2. 構造器函數

因此可以定義任何數量的參數,可以是必選、可以有類型、可以有默認值。構造器的參數放在類名後的括號裡調用。

<?php
class Point {
    protected int $x;
    protected int $y;

    public function __construct(int $x, int $y = 0) {
        $this->x = $x;
        $this->y = $y;
    }
}

// 兩個參數都傳入
$p1 = new Point(4, 5);
// 僅傳入必填的參數。 $y 會默認為0。
$p2 = new Point(4);
// 使用命名參數(PHP 8.0 起):
$p3 = new Point(y: 5, x: 4);
?>

如果一個類沒有構造函數,以及構造函數的參數不是必填項時,括號就可以省略。

析構函數

__destruct(): void

1. 析構函數範例
<?php

class MyDestructableClass 
{
    function __construct() {
        print "In constructor\n";
    }

    function __destruct() {
        print "Destroying " . __CLASS__ . "\n";
    }
}

$obj = new MyDestructableClass();

和構造函數一樣,父類的析構函數不會被引擎暗中調用。要執行父類的析構函數,必須在子類的析構函數體中顯式調用 parent::__destruct()。

此外也和構造函數一樣,子類如果自己沒有定義析構函數則會繼承父類的。 析構函數即使在使用 exit() 終止腳本運行時也會被調用。

在析構函數中調用 exit() 將會中止其餘關閉操作的運行。

注意: 析構函數在腳本關閉時調用,此時所有的 HTTP 頭信息已經發出。腳本關閉時的工作目錄有可能和在 SAPI(如 apache)中時不同

注意: 試圖在析構函數(在腳本終止時被調用)中拋出一個異常會導致致命錯誤。

資料來源: https://www.php.net/


上一篇
[Day14]PHP Class 類別01
下一篇
[Day16] 類別(Class) - private, protected, public
系列文
後端新手PHP+Laravel筆記30

尚未有邦友留言

立即登入留言