Расширение статических классов PHP
Я боролся в этой области уже несколько дней, и я пришел к выводу, но поскольку вывод не был тем, что я искал, прежде чем я сдадусь, я попытаюсь посмотреть, что говорят другие. Вера умирает последним...
Скажем, у нас есть суперкласс (называемый "Супер" ) и подкласс (называемый "Sub" ).
class Super {
protected static $title = 'super';
public static function get_class_name()
{
echo __CLASS__;
}
public static function get_title()
{
echo self::$title;
}
}
class Sub extends Super {
protected static $title = 'sub';
}
Теперь вы, вероятно, ожидаете, поскольку Sub расширяет Super, этот Sub теперь наследует все методы Super, однако, похоже, он получает только ссылки на методы Sub.
Я говорю это, потому что, если я звоню:
Sub::get_class_name();
вывод "Super", а не "Sub".
И если я звоню:
Sub::get_title();
снова, вывод "супер", и у меня даже есть заголовок $, объявленный в Sub.
Таким образом, это означает, что когда я вызываю унаследованную статическую функцию, область функций будет суперклассом, а не тем, на который вызывается (даже если вы печатаете обратную трассировку, это покажет, что вызов был сделан на суперклассе!!!), и для того, чтобы получить область видимости в качестве подкласса, на который делается вызов, мне нужно обновить этот метод внутри этого подкласса. Хорошо, этот вид побеждает цель расширения классов, не так ли?
Итак, мой вопрос: могу ли я когда-либо расширить статический класс, вызвать один из унаследованных методов и обладать областью подкласса? или, по крайней мере, иметь возможность идентифицировать это имя класса?
И если нет, то почему я хотел бы расширить статические классы?
Спасибо!
Ответы
Ответ 1
Опять же, это невозможно до PHP 5.3.0.
Поздняя статическая привязка была представлена в PHP 5.3.0 и позволяет вам делать именно то, что вы хотите с помощью static
.
class Super {
protected static $title = 'super';
public static function get_class_name()
{
echo __CLASS__;
}
public static function get_title()
{
echo static::$title;
}
}
class Sub extends Super {
protected static $title = 'sub';
}
get_class_name()
по-прежнему будет возвращать Super
, хотя __CLASS__
всегда возвращает текущий класс, который объявляется запущенным способом (вроде как __FILE__
, который всегда возвращает текущий файл независимо от того, включил ли вы его или нет).
Для этого у вас нет выбора, кроме как повторно объявить функцию в классе Sub
.
class Super {
protected static $title = 'super';
public static function get_class_name()
{
echo __CLASS__;
}
public static function get_title()
{
echo static::$title;
}
}
class Sub extends Super {
protected static $title = 'sub';
public static function get_class_name()
{
echo __CLASS__;
}
}
Ответ 2
Вы можете использовать get_called_class()
, чтобы получить имя класса вызываемого класса, даже если оно статично. Вам не нужно нигде объявлять его.
Из примера Andrew:
class Super {
public static function get_class1_name()
{
echo __CLASS__;
}
public static function get_title()
{
echo get_called_class();
}
}
class Sub extends Super {
public static function get_class2_name()
{
echo __CLASS__;
}
}
Sub::get_title(); // Echos Sub.
Sub::get_class1_Name(); // echos super
Sub::get_class2_Name(); // echos sub
Поэтому вам не нужно объявлять какие-либо переменные.
Ответ 3
К счастью, я что-то делаю для меня, поэтому я сказал, вверните его, я использую PHP5.3. Но даже в этом случае мне не нравится, что я должен обновлять "get _class _name" в каждом классе, возможно, я расширяюсь, как 10 классов. Поэтому я придумал это решение:
class Super {
protected static $classname = __CLASS__;
public static function get_classname($name)
{
static::$classname = $name;
}
public static function get_classname()
{
return static::$classname;
}
}
class Sub1 extends Super { }
class Sub2 extends Super { }
class Sub3 extends Super { }
$classes = get_declared_classes();
foreach($classes as $k => $v)
{
if (is_subclass_of($v, 'Super'))
{
$v::set_classname($v);
}
}
echo Sub1::get_classname(); // Sub1
echo Sub2::get_classname(); // Sub2
echo Sub3::get_classname(); // Sub3
Это может показаться немного грязным, но я не думаю, что это так плохо. После этого вы можете, наконец, расширить статические методы без повторного объявления методов.