PHP中的抽象常量-强制子类定义常量
我注意到,PHP中不能有抽象常量。
有没有一种方法可以强制子类定义常量(我需要在抽象类内部方法之一中使用该常量)?
Alex asked 2020-07-25T23:10:52Z
5个解决方案
41 votes
这可能有点“骇客”,但工作量很小,但如果未在子类中声明该常量,则会显示不同的错误消息。
自引用常量声明在语法上是正确的,并且可以毫无问题地进行解析,只有在该声明实际上在运行时执行时才会抛出错误,因此抽象类中的自引用声明必须在子类中被覆盖,否则将发生致命错误 :Foo。
在此示例中,抽象的父类Foo强制其所有子代声明变量Donald。此代码运行良好,输出Donald。但是,如果子类Fooling没有声明该变量,则会触发致命错误。
abstract class Foo {
// Self-referential 'abstract' declaration
const NAME = self::NAME;
}
class Fooling extends Foo {
// Overrides definition from parent class
// Without this declaration, an error will be triggered
const NAME = 'Donald';
}
$fooling = new Fooling();
echo $fooling::NAME;
WebSmithery answered 2020-07-25T23:13:14Z
28 votes
constant是constant; 据我所知,PHP中没有abstract或private常量,但是您可以解决以下问题:
样本摘要类
abstract class Hello {
const CONSTANT_1 = 'abstract'; // Make Abstract
const CONSTANT_2 = 'abstract'; // Make Abstract
const CONSTANT_3 = 'Hello World'; // Normal Constant
function __construct() {
Enforcer::__add(__CLASS__, get_called_class());
}
}
这样会很好
class Foo extends Hello {
const CONSTANT_1 = 'HELLO_A';
const CONSTANT_2 = 'HELLO_B';
}
new Foo();
酒吧将返回错误
class Bar extends Hello {
const CONSTANT_1 = 'BAR_A';
}
new Bar();
Songo将返回错误
class Songo extends Hello {
}
new Songo();
强制类
class Enforcer {
public static function __add($class, $c) {
$reflection = new ReflectionClass($class);
$constantsForced = $reflection->getConstants();
foreach ($constantsForced as $constant => $value) {
if (constant("$c::$constant") == "abstract") {
throw new Exception("Undefined $constant in " . (string) $c);
}
}
}
}
Baba answered 2020-07-25T23:12:44Z
18 votes
不幸的是,不是……一个常数正是它在锡上所说的常数。 一旦定义了它,就无法重新定义,因此,以这种方式,不可能通过PHP的抽象继承或接口来要求对其进行定义。
但是...您可以检查常量是否在父类的构造函数中定义。 如果不是,则抛出异常。
abstract class A
{
public function __construct()
{
if (!defined('static::BLAH'))
{
throw new Exception('Constant BLAH is not defined on subclass ' . get_class($this));
}
}
}
class B extends A
{
const BLAH = 'here';
}
$b = new B();
这是我可以从您的初始描述中想到的最佳方法。
Jamie Rumbelow answered 2020-07-25T23:13:43Z
7 votes
不,但是您可以尝试其他方法,例如抽象方法:
abstract class Fruit
{
abstract function getName();
abstract function getColor();
public function printInfo()
{
echo "The {$this->getName()} is {$this->getColor()}";
}
}
class Apple extends Fruit
{
function getName() { return 'apple'; }
function getColor() { return 'red'; }
//other apple methods
}
class Banana extends Fruit
{
function getName() { return 'banana'; }
function getColor() { return 'yellow'; }
//other banana methods
}
或静态成员:
abstract class Fruit
{
protected static $name;
protected static $color;
public function printInfo()
{
echo "The {static::$name} is {static::$color}";
}
}
class Apple extends Fruit
{
protected static $name = 'apple';
protected static $color = 'red';
//other apple methods
}
class Banana extends Fruit
{
protected static $name = 'banana';
protected static $color = 'yellow';
//other banana methods
}
资源
Songo answered 2020-07-25T23:14:11Z
1 votes
在php 7.2中进行了测试,但从5.3开始,您可以利用后期静态绑定来存档此行为。 由于与大多数情况相同,它会引发致命错误,因为在大多数情况下,您都不希望在运行时处理致命错误。如果需要,可以轻松实现自定义错误处理程序。
所以以下对我有用:
abstract class Foo {
public function __construct() {
echo static::BAR;
}
}
class Bar extends Foo {
const BAR = "foo bar";
}
$bar = new Bar(); //foo bar
如果卸下const,则会得到:
Fatal error: Uncaught Error: Undefined class constant 'BAR' in ...
Code Spirit answered 2020-07-25T23:14:40Z