I noticed that you can't have abstract constants in PHP.
我注意到你不能在PHP中有抽象常量。
Is there a way I can force a child class to define a constant (which I need to use in one of the abstract class internal methods) ?
有没有办法可以强制子类定义一个常量(我需要在其中一个抽象类内部方法中使用)?
4 个解决方案
#1
26
A constant
is a constant
; there is no abstract
or private
constants in PHP as far as I know, but you can have a work around:
常数是常数;据我所知,PHP中没有抽象或私有常量,但你可以解决一下:
Sample Abstract Class
样本抽象类
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());
}
}
This would run fine
这样运行正常
class Foo extends Hello {
const CONSTANT_1 = 'HELLO_A';
const CONSTANT_2 = 'HELLO_B';
}
new Foo();
Bar would return Error
Bar会返回Error
class Bar extends Hello {
const CONSTANT_1 = 'BAR_A';
}
new Bar();
Songo would return Error
Songo将返回Error
class Songo extends Hello {
}
new Songo();
Enforcer Class
执行者类
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);
}
}
}
}
#2
16
This may be a bit of a ‘hack’, but does the job with very little effort, but just with a different error message if the constant is not declared in the child class.
这可能是一个“黑客”,但只需很少的努力就可以完成工作,但如果未在子类中声明常量,则只需使用不同的错误消息。
A self-referential constant declaration is syntactically correct and parses without problem, only throwing an error if that declaration is actually executed at runtime, so a self-referential declaration in the abstract class must be overridden in a child class else there will be fatal error: Cannot declare self-referencing constant
.
自引用常量声明在语法上是正确的并且解析没有问题,只有在运行时实际执行该声明时才抛出错误,因此必须在子类中重写抽象类中的自引用声明否则会出现致命错误:不能声明自引用常量。
In this example, the abstract, parent class Foo
forces all its children to declare the variable NAME
. This code runs fine, outputting Donald
. However, if the child class Fooling
did not declare the variable, the fatal error would be triggered.
在此示例中,抽象父类Foo强制其所有子节点声明变量NAME。这段代码运行正常,输出唐纳德。但是,如果子类Fooling没有声明变量,则会触发致命错误。
<?php
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;
#3
15
Unfortunately not... a constant is exactly what it says on the tin, constant. Once defined it can't be redefined, so in that way, it is impossible to require its definition through PHP's abstract inheritance or interfaces.
不幸的是,不是......一个常数正是它在锡上所说的,不变的。一旦定义,就无法重新定义,因此以这种方式,不可能通过PHP的抽象继承或接口来定义它的定义。
However... you could check to see if the constant is defined in the parent class's constructor. If it doesn't, throw an Exception.
但是......您可以检查是否在父类的构造函数中定义了常量。如果没有,则抛出异常。
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();
This is the best way I can think of doing this from your initial description.
这是我从最初的描述中想到的最佳方式。
#4
7
No, yet you could try other ways such as abstract methods:
不,你可以尝试其他方法,如抽象方法:
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
}
or static members:
或静态成员:
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
}
资源
#1
26
A constant
is a constant
; there is no abstract
or private
constants in PHP as far as I know, but you can have a work around:
常数是常数;据我所知,PHP中没有抽象或私有常量,但你可以解决一下:
Sample Abstract Class
样本抽象类
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());
}
}
This would run fine
这样运行正常
class Foo extends Hello {
const CONSTANT_1 = 'HELLO_A';
const CONSTANT_2 = 'HELLO_B';
}
new Foo();
Bar would return Error
Bar会返回Error
class Bar extends Hello {
const CONSTANT_1 = 'BAR_A';
}
new Bar();
Songo would return Error
Songo将返回Error
class Songo extends Hello {
}
new Songo();
Enforcer Class
执行者类
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);
}
}
}
}
#2
16
This may be a bit of a ‘hack’, but does the job with very little effort, but just with a different error message if the constant is not declared in the child class.
这可能是一个“黑客”,但只需很少的努力就可以完成工作,但如果未在子类中声明常量,则只需使用不同的错误消息。
A self-referential constant declaration is syntactically correct and parses without problem, only throwing an error if that declaration is actually executed at runtime, so a self-referential declaration in the abstract class must be overridden in a child class else there will be fatal error: Cannot declare self-referencing constant
.
自引用常量声明在语法上是正确的并且解析没有问题,只有在运行时实际执行该声明时才抛出错误,因此必须在子类中重写抽象类中的自引用声明否则会出现致命错误:不能声明自引用常量。
In this example, the abstract, parent class Foo
forces all its children to declare the variable NAME
. This code runs fine, outputting Donald
. However, if the child class Fooling
did not declare the variable, the fatal error would be triggered.
在此示例中,抽象父类Foo强制其所有子节点声明变量NAME。这段代码运行正常,输出唐纳德。但是,如果子类Fooling没有声明变量,则会触发致命错误。
<?php
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;
#3
15
Unfortunately not... a constant is exactly what it says on the tin, constant. Once defined it can't be redefined, so in that way, it is impossible to require its definition through PHP's abstract inheritance or interfaces.
不幸的是,不是......一个常数正是它在锡上所说的,不变的。一旦定义,就无法重新定义,因此以这种方式,不可能通过PHP的抽象继承或接口来定义它的定义。
However... you could check to see if the constant is defined in the parent class's constructor. If it doesn't, throw an Exception.
但是......您可以检查是否在父类的构造函数中定义了常量。如果没有,则抛出异常。
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();
This is the best way I can think of doing this from your initial description.
这是我从最初的描述中想到的最佳方式。
#4
7
No, yet you could try other ways such as abstract methods:
不,你可以尝试其他方法,如抽象方法:
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
}
or static members:
或静态成员:
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
}
资源