PHP - заставить класс объявить свойство

У меня есть набор классов, которые расширяют абстрактный класс. Абстрактный класс содержит методы, которые используют поздние статические привязки для получения информации, которая определена в дочерних классах. Так, например, абстрактный класс может иметь метод, содержащий строку:

$var = static::$childVar . ' some text';

Таким образом, во время выполнения для метода, определенного в абстрактном классе, можно генерировать разные строки на основе значения переменной, определенной в дочерних классах.

Что я хочу сделать, так это иметь некоторый механизм, который заставляет дочерние классы объявлять эту переменную, исключая возможность вызова метода, если переменная не установлена.

Используя интерфейсы, можно потребовать, чтобы класс определял методы (и константы, которые, к сожалению, не могут изменять их видимость с использованием public/protected/private). Поэтому, если класс реализует интерфейс, но не определяет все методы, указанные в интерфейсе, генерируется ошибка. Тем не менее, нет способа использовать интерфейс, чтобы требовать от класса определения свойства.

Я видел некоторый материал, который предлагает использовать методы getter в интерфейсе (например, getChildVar()), чтобы неявно требовать объявление переменной, но это не подходит для меня, поскольку я не хочу, чтобы переменные были доступны вне класса ( они имеют видимость protected).

Аналогично, константы не будут работать, потому что они не поддерживают модификатор видимости protected.

Я знаю, что всегда мог использовать оператор isset() для проверки этого в методе (или даже в конструкторе) абстрактного класса, но это кажется неэлегантным по сравнению с использованием интерфейсов для обеспечения методов. Мне интересно, есть ли стандартный способ сделать это без жесткого кодирования требований в моем абстрактном классе.

Кстати, если кто-нибудь знает, почему вы не можете объявлять переменные внутри интерфейсов, мне было бы интересно узнать, что такое рассуждение. Мне кажется, что это большой надзор.

Любая помощь будет очень оценена.

Ответ 1

Вы не можете применять переменные в интерфейсе, потому что интерфейс является публичным представлением о том, как использовать ваш класс. Если я еще один разработчик, прыгающий на борт с вашим проектом, я хочу иметь возможность посмотреть на интерфейс и знать, что все методы, которые я могу предположить, реализованы в классах, которые, ну, реализуют этот интерфейс. Это не все, что актуально для частных или защищенных свойств или, действительно, для любого конкретного свойства. Getters/seters являются стандартом для такого рода вещей.

Надзор прямо сейчас заключается в том, что у вас не может быть волшебного метода для доступа к статическому свойству undefined. Это было бы идеальным решением для вас здесь.

Если статическое свойство объявлено во время выполнения, почему бы не применять метод setChildVar() или не применять метод родительского класса, который получает свойство с поздней статикой и выдает ошибку, если он не установлен? Вы даже можете реализовать шаблон "драйвер", чтобы выполнить это:

<?php

class MyParentClass {

    public function __get($key)
    {
        if ( !isset(static::$$key))
        {
            throw new Exception('Child class '.get_called_class().' failed to define static '.$key.' property');
        }

        return static::$$key;
    }

    public function getText()
    {
        return $this->childVar . ' some text';
    }

}

class MyChildClass extends MyParentClass {

    protected static $childVar = 'some value:';

}

$a = new MyChildClass;
echo $a->getText(); // some value: some text