在PHP摘要常数 - 强制子类定义常量(Abstract constants in PHP - Fo

2019-06-24 01:13发布

我注意到,你不能在PHP抽象的常量。

有没有一种方法,我可以强制其子类来定义常量(这是我需要的抽象类的内部方法之一来使用)?

Answer 1:

constant是一个constant ; 没有abstractprivate的PHP常量,据我所知,但你可以有一个变通:

样品抽象类

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();

松戈将返回错误

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);
            }
        }
    }
}


Answer 2:

这可能是一个有点“黑客”的,但确实用很少的努力工作,只是用不同的错误消息,如果不断在子类中没有声明。

自引用的常量声明语法正确,并解析没有问题,只有在该声明是在运行时实际执行抛出一个错误,所以在抽象类中的自我指涉的声明必须在子类中重写否则就会出现致命错误: Cannot declare self-referencing constant

在这个例子中,抽象的,父类Foo力所有子声明变量NAME 。 此代码运行正常,输出Donald 。 但是,如果子类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;


Answer 3:

不幸的是不是......恒定正是它在锡说,不变。 一旦定义它不能被重新定义,所以在这种方式,它不可能需要通过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();

这是我能想到的,从您最初的说明这样做的最佳方式。



Answer 4:

没有,但你可以尝试其他的方法,如抽象方法:

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
} 

资源



Answer 5:

经测试,在PHP 7.2,但应该因为5.3,你可以利用后期静态绑定归档此行为。 它会抛出一个致命错误achchieving同一个例外,因为在大多数的原因你不想在运行时处理的致命错误。 如果你想要让你可以轻松实现自定义错误处理程序。

所以下面的工作对我来说:

<?php

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 ...


文章来源: Abstract constants in PHP - Force a child class to define a constant