Я заметил, что в PHP не может быть абстрактных констант.
Есть ли способ заставить дочерний класс определить константу (которую мне нужно использовать в одном из внутренних методов абстрактного класса)?
Я заметил, что в PHP не может быть абстрактных констант.
Есть ли способ заставить дочерний класс определить константу (которую мне нужно использовать в одном из внутренних методов абстрактного класса)?
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();
Bar вернет ошибку
class Bar extends Hello {
const CONSTANT_1 = 'BAR_A';
}
new Bar();
Songo вернет ошибку
class Songo extends Hello {
}
new Songo();
Класс Enforcer
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);
}
}
}
}
constant
в классе abstract
обрабатываются как abstract
, но все определения constant
в дочернем просто не принудительно ... На этот раз я понял @Songo
- person Baba; 29.04.2012
A constant is a constant .. there is no abstract or private
, это просто пример обходного пути.. не идеальный, не для использования в производстве... только в образовательных целях.... Если у вас есть лучшее решение, просто добавьте его...
- person Baba; 27.10.2012
Это может быть что-то вроде «хака», но делает работу с очень небольшими усилиями, но с другим сообщением об ошибке, если константа не объявлена в дочернем классе.
Объявление самореферентной константы синтаксически корректно и анализируется без проблем, выдавая ошибку только в том случае, если это объявление действительно выполняется во время выполнения, поэтому самореферентное объявление в абстрактном классе должно быть переопределено в дочернем классе. class иначе будет фатальная ошибка: 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;
static::NAME
- person Lucas Bustamante; 12.09.2019
define
, хотя обычно константу класса можно указать через define
(PHP 7.3.11).
- person Jake; 06.08.2020
К сожалению, нет... константа - это именно то, что написано на банке, константа. После определения его нельзя переопределить, поэтому невозможно требовать его определения через абстрактное наследование или интерфейсы 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();
Это лучший способ сделать это из вашего первоначального описания.
Нет, но вы можете попробовать другие способы, такие как абстрактные методы:
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
}
Протестировано в php 7.2, но начиная с 5.3 вы можете использовать позднюю статическую привязку для архивирования этого поведения. Это вызовет Fatal Error, достигающую того же, что и Exception, потому что в большинстве случаев вы не хотите обрабатывать Fatal Errors во время выполнения. Если вы хотите, вы можете легко реализовать собственный обработчик ошибок.
Итак, для меня работает следующее:
<?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 ...
echo static::BAR;
. IDE или статический анализатор не сообщат автору класса Bar, что он должен определить константу.
- person bdsl; 04.08.2020
Интерфейсы PHP поддерживают константы. Это не так идеально, потому что вам нужно помнить о реализации интерфейса в каждом дочернем классе, поэтому это частично противоречит цели.