Подтвердить что ты не робот

Абстрактные константы в PHP. Заставьте дочерний класс определить константу

Я заметил, что вы не можете иметь абстрактные константы в PHP.

Есть ли способ заставить дочерний класс определять константу (которую я должен использовать в одном из внутренних методов абстрактного класса)?

4b9b3361

Ответ 1

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

Ответ 2

К сожалению, не... константа - это именно то, что она говорит о жесте, постоянное. После определения он не может быть переопределен, поэтому таким образом невозможно определить его определение через наследование или интерфейсы абстрактного 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();

Это лучший способ, я могу думать об этом из вашего первоначального описания.

Ответ 3

Это может быть немного "взломать", но делает работу с очень небольшим усилием, но просто с другим сообщением об ошибке, если константа не объявлена ​​в дочернем классе.

Объявление самореференциальной константы синтаксически корректно и анализирует без проблем, только бросая ошибку, если это объявление действительно выполняется во время выполнения, поэтому самореференциальное объявление в абстрактном классе должно быть переопределено в дочернем классе, иначе будет фатальная ошибка: 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;

Ответ 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
} 

Источник