Я заметил, что вы не можете иметь абстрактные константы в 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
}