我有一个定义几个常量的抽象类。大多数这些常量都不会被任何子类覆盖,但一个应该。 我在抽象类中将此常量定义为null,并在子类中为其指定值。所有子类中的构造函数也是相同的,因此我添加了一个检查以查看是否为该常量赋值,如果未由子类定义则抛出异常。
草拟我的问题的一些简化代码:
父抽象类:
abstract class ParentClass {
const TEST_CONSTANT = null;
public function __construct()
{
if (!defined(self::TEST_CONSTANT)) {
throw new Exception("Please define TEST_CONSTANT!");
}
}
abstract protected function someFunction();
}
儿童班:
class ChildClass extends ParentClass {
const TEST_CONSTANT = "value";
protected function someFunction()
{
//some functionality here
}
}
但是,在实例化ChildClass时,异常"请定义TEST_CONSTANT!"即使常数被覆盖,也会被抛出。我理解我可以简单地将它作为构造函数中的必需参数,并以这种方式设置成员变量(这可能是更符合逻辑/实际的解决方案)。
就我而言,为此目的使用常量可能没什么意义,但我仍然想了解为什么这不起作用。 应该可以覆盖子类中的常量。在调用构造函数之后,这种覆盖是否只会发生?我的支票不正确吗?很高兴理解这里发生的事件的逻辑和顺序。
答案 0 :(得分:2)
您需要将参数作为字符串传递给defined()
:
if (!defined('self::TEST_CONSTANT')) {
否则,你正在测试是否存在一个名为null的全局常量(不是' null'而是一个实际的null,这是非常无意义的)....如果你'尝试确定是否定义了名为value
的全局常量,那么您可能还需要考虑使用static::TEST_CONSTANT
,这将取代您所在的子类中static::TEST_CONSTANT
的值。已实例化('value'
)并测试以查看是否已定义名为value
的全局常量。
答案 1 :(得分:1)
您需要使用late static building从父类访问静态子属性(和常量):
abstract class ParentClass {
const TEST_CONSTANT = null;
public function __construct()
{
if (!defined(static::TEST_CONSTANT)) {
throw new Exception("Please define TEST_CONSTANT!");
}
}
abstract protected function someFunction();
}
说,覆盖常量看起来有点不寻常。我很好奇usecase为什么你需要它。