W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
__construct(mixed ...$values = ""): void
PHP 允許開發(fā)者在一個類中定義一個方法作為構造函數(shù)。具有構造函數(shù)的類會在每次創(chuàng)建新對象時先調(diào)用此方法,所以非常適合在使用對象之前做一些初始化工作。
注意: 如果子類中定義了構造函數(shù)則不會隱式調(diào)用其父類的構造函數(shù)。要執(zhí)行父類的構造函數(shù),需要在子類的構造函數(shù)中調(diào)用 parent::__construct()。如果子類沒有定義構造函數(shù)則會如同一個普通的類方法一樣從父類繼承(假如沒有被定義為 private 的話)。
示例 #1 繼承中的構造函數(shù)
<?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 的構造函數(shù)
}
// In BaseClass constructor
$obj = new BaseClass();
// In BaseClass constructor
// In SubClass constructor
$obj = new SubClass();
// In BaseClass constructor
$obj = new OtherSubClass();
?>
與其它方法不同, __construct() 在繼承時不受簽名兼容性規(guī)則的約束。
自 PHP 5.3.3 起,在命名空間中,與類名同名的方法不再作為構造函數(shù)。不使用命名空間中的類則不受影響。 構造函數(shù)是一個普通的方法,在對應對象實例化時自動被調(diào)用。 因此可以定義任何數(shù)量的參數(shù),可以是必選、可以有類型、可以有默認值。 構造器的參數(shù)放在類名后的括號里調(diào)用。
示例 #2 使用構造器參數(shù)
<?php
class Point {
protected int $x;
protected int $y;
public function __construct(int $x, int $y = 0) {
$this->x = $x;
$this->y = $y;
}
}
// 兩個參數(shù)都傳入
$p1 = new Point(4, 5);
// 僅傳入必填的參數(shù)。 $y 會默認取值 0。
$p2 = new Point(4);
// 使用命名參數(shù)(PHP 8.0 起):
$p3 = new Point(y: 5, x: 4);
?>
如果一個類沒有構造函數(shù),以及構造函數(shù)的參數(shù)不是必填項時,括號就可以省略。
PHP 8.0.0 之前,全局命名空間內(nèi)的類如果有一個同名的方法,則會解析為舊式風格的構造器。 雖然函數(shù)能被當作構造器,但該語法已被廢棄,并會導致 E_DEPRECATED 錯誤。 如果 __construct() 和同名方法同時存在時, 會調(diào)用 __construct()。
以下兩種情況時,與類同名的方法不再有特殊意義:命名空間中的類、PHP 8.0.0 起的任何類。
新代碼中要使用 __construct()。
PHP 8.0.0 起,構造器的參數(shù)也可以相應提升為類的屬性。 構造器的參數(shù)賦值給類屬性的行為很普遍,否則無法操作。 而構造器提升的功能則為這種場景提供了便利。 因此上面的例子可以用以下方式重寫:
示例 #3 使用構造器屬性提升
<?php
class Point {
public function __construct(protected int $x, protected int $y = 0) {
}
}
當構造器參數(shù)帶訪問控制(visibility modifier)時,PHP 會同時把它當作對象屬性和構造器參數(shù), 并賦值到屬性。 構造器可以是空的,或者包含其他語句。 參數(shù)值賦值到相應屬性后執(zhí)行正文中額外的代碼語句。
并非所有參數(shù)都需要提升??梢曰旌咸嵘虿惶嵘齾?shù)作為屬性,也不需要按順序。 提升后的參數(shù)不影響構造器內(nèi)代碼調(diào)用。
注意:對象屬性的類型不能為 callable 以避免為引擎帶來混淆。 因此提升的參數(shù)也不能是 callable。 其他任意 類型聲明 是允許的。
注意:放在構造方法提升參數(shù)里的屬性會同時復制為屬性和參數(shù)。提升的構造方法的參數(shù)默認值將僅復制到參數(shù)并且不會復制到屬性。
自 PHP 8.1.0 起,對象可以用于默認參數(shù)值,靜態(tài)變量,全局常量,以及屬性參數(shù)。define() 現(xiàn)在也接受對象。
注意:禁止使用動態(tài)類名、非字符串類名以及匿名類。禁止使用參數(shù)解包。禁止使用不支持的表達式作為參數(shù)。
示例 #4 初始化中使用 new
<?php
// 全部允許:
static $x = new Foo;
const C = new Foo;
function test($param = new Foo) {}
#[AnAttribute(new Foo)]
class Test {
public function __construct(
public $prop = new Foo,
) {}
}
// 全部禁止(編譯時錯誤):
function test(
$a = new (CLASS_NAME_CONSTANT)(), // 動態(tài)類名
$b = new class {}, // 匿名類
$c = new A(...[]), // 參數(shù)解包
$d = new B($abc), // 不支持的常量表達式
) {}
?>
在 PHP 中每個 class 只能有一個構造器。 然而有些情況下,需要用不同的輸入實現(xiàn)不同的方式構造對象。 這種情況下推薦使用 static 方法包裝構造。
示例 #5 使用 static 創(chuàng)造方法
<?php
class Product {
private ?int $id;
private ?string $name;
private function __construct(?int $id = null, ?string $name = null) {
$this->id = $id;
$this->name = $name;
}
public static function fromBasicData(int $id, string $name): static {
$new = new static($id, $name);
return $new;
}
public static function fromJson(string $json): static {
$data = json_decode($json);
return new static($data['id'], $data['name']);
}
public static function fromXml(string $xml): static {
// 自定義代碼邏輯。
$data = convert_xml_to_array($xml);
$new = new static();
$new->id = $data['id'];
$new->name = $data['name'];
return $new;
}
}
$p1 = Product::fromBasicData(5, 'Widget');
$p2 = Product::fromJson($some_json_string);
$p3 = Product::fromXml($some_xml_string);
可以設置構造器為 private 或 protected,防止自行額外調(diào)用。 這時只有 static 方法可以實例化一個類。 由于它們位于同一個定義的 class 因此可以訪問私有方法,也不需要在同一個對象實例中。 當然構造器不一定要設置為 private,是否合理取決于實際情況。
三個 static 方法展示了對象以不同方式的實例化方式。
在以上三個例子中,static 關鍵詞會被翻譯成代碼所在類的類名。 這個例子中是 Product。
__destruct(): void
PHP 有析構函數(shù)的概念,這類似于其它面向?qū)ο蟮恼Z言,如 C++。析構函數(shù)會在到某個對象的所有引用都被刪除或者當對象被顯式銷毀時執(zhí)行。
示例 #6 析構函數(shù)示例
<?php
class MyDestructableClass
{
function __construct() {
print "In constructor\n";
}
function __destruct() {
print "Destroying " . __CLASS__ . "\n";
}
}
$obj = new MyDestructableClass();
和構造函數(shù)一樣,父類的析構函數(shù)不會被引擎暗中調(diào)用。要執(zhí)行父類的析構函數(shù),必須在子類的析構函數(shù)體中顯式調(diào)用 parent::__destruct()。此外也和構造函數(shù)一樣,子類如果自己沒有定義析構函數(shù)則會繼承父類的。
析構函數(shù)即使在使用 exit() 終止腳本運行時也會被調(diào)用。在析構函數(shù)中調(diào)用 exit() 將會中止其余關閉操作的運行。
注意:析構函數(shù)在腳本關閉時調(diào)用,此時所有的 HTTP 頭信息已經(jīng)發(fā)出。腳本關閉時的工作目錄有可能和在 SAPI(如 apache)中時不同。
注意:試圖在析構函數(shù)(在腳本終止時被調(diào)用)中拋出一個異常會導致致命錯誤。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: