调用构造函数时静态 属性 未初始化 php
static property not initialised when constructor is called php
我有一个 parent class 像这样:
abstract class UiElement
{
protected static ?string $template_name = null;
public function __construct() {
if(static::$template_name == null) {
throw new Exception("static $template_name has not been set in child class", 1);
}
}
}
现在我有一个 child class 像这样:
class EmptyContent extends UiElement
{
protected static ?string $template_name = 'empty-content';
public function __construct() {
parent::__construct();
}
}
并这样称呼它:
$empty = new EmptyContent();
我想确保 child class 在这种情况下 EmptyContent
在定义此 class 时设置了一个非 null 的值。所以我在 parent 的 class 构造函数中进行了检查,但这给了我以下错误:
Fatal error: Uncaught Exception: static $template_name has not been set in child class in /Applications/MAMP/htdocs/private_projects/Foodio/App/index.php:108 Stack trace: #0 /Applications/MAMP/htdocs/private_projects/Foodio/App/index.php(126): UiElement->__construct() #1 /Applications/MAMP/htdocs/private_projects/Foodio/App/index.php(134): failure->__construct() #2 {main} thrown in
据我所知,这是因为 属性 $template_name
在 parent 的构造函数被触发时尚未初始化。
我该怎么做?
如果需要更多信息或说明,请告诉我,以便我添加!
按照建议,您可以使用抽象方法强制实现 类 来定义它:
abstract class UiElement
{
abstract protected function getTemplateName(): string;
}
然后,实现 类 应该定义什么字符串 return:
class EmptyContent extends UiElement
{
protected function getTemplateName(): string
{
return 'empty-content';
}
}
这意味着你想在任何地方使用这个值,你必须通过调用 $this->getTemplateName()
来检索它。
您可以创建一个抽象方法而不是 属性:
abstract class UiElement
{
abstract protected static function getTemplateName(): string;
}
class EmptyContent extends UiElement
{
protected static function getTemplateName(): string
{
return 'empty-content';
}
}
这样你就不能在没有实现的方法(强制定义)的情况下创建 child class。你应该创建一个没有它的 child:
class EmptyContent extends UiElement
{
}
PHP 将在 运行 您的脚本之前抛出致命错误:Class EmptyContent contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (UiElement::getTemplateName)
.
现在,这有它的缺点。它不会保护您免于实施空方法或 return 类型错误的方法。那种东西只会在你用的时候在你脸上爆炸。您可以通过向 child 添加一个构造函数来防止这种情况(另外检查您没有 return 一个空字符串):
class EmptyContent extends UiElement
{
public function __construct()
{
if (strlen(self::getTemplateName()) === 0) {
throw new Exception('Template name is not defined');
}
}
...
为了强制检查实例化。这必须添加到每个 child(乏味和潮湿),因为您无法在 parent 级别处理它(这将尝试调用其抽象方法并在到达运行时之前失败)。
您还可以采用另一种方法,使其成为常规 (non-abstract) 方法,并在 parent:
中抛出
abstract class UiElement
{
protected function getTemplateName(): string
{
throw new Exception('Method not implemented');
}
}
仅当您尝试在 child 上使用该方法(而不是在实例化期间)时,这也会失败,该方法未实现该方法,但会在 [=40 内部的一个地方处理=].利弊由你权衡
P.S。
不确定如果只在内部使用该方法是否真的需要静态,但您比我更了解您的推理。
我有一个 parent class 像这样:
abstract class UiElement
{
protected static ?string $template_name = null;
public function __construct() {
if(static::$template_name == null) {
throw new Exception("static $template_name has not been set in child class", 1);
}
}
}
现在我有一个 child class 像这样:
class EmptyContent extends UiElement
{
protected static ?string $template_name = 'empty-content';
public function __construct() {
parent::__construct();
}
}
并这样称呼它:
$empty = new EmptyContent();
我想确保 child class 在这种情况下 EmptyContent
在定义此 class 时设置了一个非 null 的值。所以我在 parent 的 class 构造函数中进行了检查,但这给了我以下错误:
Fatal error: Uncaught Exception: static $template_name has not been set in child class in /Applications/MAMP/htdocs/private_projects/Foodio/App/index.php:108 Stack trace: #0 /Applications/MAMP/htdocs/private_projects/Foodio/App/index.php(126): UiElement->__construct() #1 /Applications/MAMP/htdocs/private_projects/Foodio/App/index.php(134): failure->__construct() #2 {main} thrown in
据我所知,这是因为 属性 $template_name
在 parent 的构造函数被触发时尚未初始化。
我该怎么做?
如果需要更多信息或说明,请告诉我,以便我添加!
按照建议,您可以使用抽象方法强制实现 类 来定义它:
abstract class UiElement
{
abstract protected function getTemplateName(): string;
}
然后,实现 类 应该定义什么字符串 return:
class EmptyContent extends UiElement
{
protected function getTemplateName(): string
{
return 'empty-content';
}
}
这意味着你想在任何地方使用这个值,你必须通过调用 $this->getTemplateName()
来检索它。
您可以创建一个抽象方法而不是 属性:
abstract class UiElement
{
abstract protected static function getTemplateName(): string;
}
class EmptyContent extends UiElement
{
protected static function getTemplateName(): string
{
return 'empty-content';
}
}
这样你就不能在没有实现的方法(强制定义)的情况下创建 child class。你应该创建一个没有它的 child:
class EmptyContent extends UiElement
{
}
PHP 将在 运行 您的脚本之前抛出致命错误:Class EmptyContent contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (UiElement::getTemplateName)
.
现在,这有它的缺点。它不会保护您免于实施空方法或 return 类型错误的方法。那种东西只会在你用的时候在你脸上爆炸。您可以通过向 child 添加一个构造函数来防止这种情况(另外检查您没有 return 一个空字符串):
class EmptyContent extends UiElement
{
public function __construct()
{
if (strlen(self::getTemplateName()) === 0) {
throw new Exception('Template name is not defined');
}
}
...
为了强制检查实例化。这必须添加到每个 child(乏味和潮湿),因为您无法在 parent 级别处理它(这将尝试调用其抽象方法并在到达运行时之前失败)。
您还可以采用另一种方法,使其成为常规 (non-abstract) 方法,并在 parent:
中抛出abstract class UiElement
{
protected function getTemplateName(): string
{
throw new Exception('Method not implemented');
}
}
仅当您尝试在 child 上使用该方法(而不是在实例化期间)时,这也会失败,该方法未实现该方法,但会在 [=40 内部的一个地方处理=].利弊由你权衡
P.S。 不确定如果只在内部使用该方法是否真的需要静态,但您比我更了解您的推理。