Я заметил, что вы не можете иметь абстрактные константы в PHP.
Есть ли способ заставить дочерний класс определять константу (которую я должен использовать в одном из внутренних методов абстрактного класса)?
Я заметил, что вы не можете иметь абстрактные константы в PHP.
Есть ли способ заставить дочерний класс определять константу (которую я должен использовать в одном из внутренних методов абстрактного класса)?
A constant
является constant
; по крайней мере, нет констант abstract
или private
в 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();
Бар возвращает Error
class Bar extends Hello {
const CONSTANT_1 = 'BAR_A';
}
new Bar();
Songo вернет Error
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);
}
}
}
}
К сожалению, не... константа - это именно то, что она говорит о жесте, постоянное. После определения он не может быть переопределен, поэтому таким образом невозможно определить его определение через наследование или интерфейсы абстрактного 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();
Это лучший способ, я могу думать об этом из вашего первоначального описания.
Это может быть немного "взломать", но делает работу с очень небольшим усилием, но просто с другим сообщением об ошибке, если константа не объявлена в дочернем классе.
Объявление самореференциальной константы синтаксически корректно и анализирует без проблем, только бросая ошибку, если это объявление действительно выполняется во время выполнения, поэтому самореференциальное объявление в абстрактном классе должно быть переопределено в дочернем классе, иначе будет фатальная ошибка: 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;
Нет, но вы можете попробовать другие способы, такие как абстрактные методы:
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
}