類常量
類常量提供了一種在程式中儲存固定值的機制。也就是說,它們提供了一種給 3.14
或 Apple
這樣的值賦予名稱(以及相關的編譯時檢查)的方法。類常量只能使用 const
關鍵字定義 - define函式不能在此上下文中使用。
作為示例,在整個程式中具有π值的速記表示可能是方便的。具有 const
值的類提供了一種儲存此類值的簡單方法。
class MathValues {
const PI = M_PI;
const PHI = 1.61803;
}
$area = MathValues::PI * $radius * $radius;
可以通過在類上使用雙冒號運算子(所謂的範圍解析運算子)來訪問類常量,就像靜態變數一樣。但是,與靜態變數不同,類常量的值在編譯時是固定的,不能重新分配(例如,MathValues::PI = 7
會產生致命錯誤)。
類常量對於定義可能需要稍後更改的類內部事物(但不要經常更改以保證儲存在資料庫中)也很有用。我們可以使用 self
scope resolutor 在內部引用它(它在例項和靜態實現中都有效)
class Labor {
/** How long, in hours, does it take to build the item? */
const LABOR_UNITS = 0.26;
/** How much are we paying employees per hour? */
const LABOR_COST = 12.75;
public function getLaborCost($number_units) {
return (self::LABOR_UNITS * self::LABOR_COST) * $number_units;
}
}
類常量只能包含版本<5.6 中的標量值
從 PHP 5.6 開始,我們可以使用帶常量的表示式,這意味著數學語句和帶連線的字串是可接受的常量
class Labor {
/** How much are we paying employees per hour? Hourly wages * hours taken to make */
const LABOR_COSTS = 12.75 * 0.26;
public function getLaborCost($number_units) {
return self::LABOR_COSTS * $number_units;
}
}
從 PHP 7.0 開始,使用 define
宣告的常量現在可能包含陣列。
define("BAZ", array('baz'));
類常量不僅僅用於儲存數學概念。例如,如果準備餡餅,可以方便地使用單個 Pie
類來製作不同種類的水果。
class Pie {
protected $fruit;
public function __construct($fruit) {
$this->fruit = $fruit;
}
}
然後我們可以像這樣使用 Pie
類
$pie = new Pie("strawberry");
這裡出現的問題是,在例項化 Pie
類時,沒有提供關於可接受值的指導。例如,當製作 boysenberry
餡餅時,它可能拼寫錯誤的 boisenberry
。此外,我們可能不支援李子餡餅。相反,有一個已經定義的可接受水果型別列表是有用的,它可以在某個地方找到它們。說一個名為 Fruit
的類:
class Fruit {
const APPLE = "apple";
const STRAWBERRY = "strawberry";
const BOYSENBERRY = "boysenberry";
}
$pie = new Pie(Fruit::STRAWBERRY);
將可接受的值列為類常量可提供有關方法接受的可接受值的有用提示。它還確保拼寫錯誤無法通過編譯器。雖然 new Pie('aple')
和 new Pie('apple')
都是編譯器可以接受的,但 new Pie(Fruit::APLE)
會產生編譯器錯誤。
最後,使用類常量意味著可以在單個位置修改常量的實際值,並且使用常量的任何程式碼都會自動具有修改的效果。
雖然訪問類常量的最常用方法是 MyClass::CONSTANT_NAME
,但它也可以通過以下方式訪問:
echo MyClass::CONSTANT;
$classname = "MyClass";
echo $classname::CONSTANT; // As of PHP 5.3.0
PHP 中的類常量通常以大寫形式命名,下劃線為單詞分隔符,但任何有效的標籤名稱都可以用作類常量名稱。
從 PHP 7.1 開始,現在可以使用預設公共範圍中的不同可見性來定義類常量。這意味著現在可以定義 protected 和 private 常量,以防止類常量不必要地洩漏到公共範圍中(請參閱方法和屬性可見性 )。例如:
class Something {
const PUBLIC_CONST_A = 1;
public const PUBLIC_CONST_B = 2;
protected const PROTECTED_CONST = 3;
private const PRIVATE_CONST = 4;
}
定義 vs 類常量
雖然這是一個有效的結構:
function bar() { return 2; };
define('BAR', bar());
如果你嘗試對類常量執行相同操作,則會出現錯誤:
function bar() { return 2; };
class Foo {
const BAR = bar(); // Error: Constant expression contains invalid operations
}
但你可以這樣做:
function bar() { return 2; };
define('BAR', bar());
class Foo {
const BAR = BAR; // OK
}
有關更多資訊,請參閱手冊中的常量 。
使用:: class 來檢索類的名稱
PHP 5.5 引入了::class
語法來檢索完整的類名,將名稱空間範圍和 use
語句考慮在內。
namespace foo;
use bar\Bar;
echo json_encode(Bar::class); // "bar\\Bar"
echo json_encode(Foo::class); // "foo\\Foo"
echo json_encode(\Foo::class); // "Foo"
即使甚至沒有定義類(即此程式碼片段單獨工作),上述工作仍然有效。
此語法對需要類名的函式很有用。例如,它可以與 class_exists
一起用來檢查一個類是否存在。無論此程式碼段中的返回值如何,都不會生成任何錯誤:
class_exists(ThisClass\Will\NeverBe\Loaded::class, false);