类常量
类常量提供了一种在程序中保存固定值的机制。也就是说,它们提供了一种给 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);