Расширение статических классов PHP
Я боролся в этой области уже несколько дней, и я пришел к выводу, но, поскольку этот вывод был не тем, что я искал, прежде чем сдаться, я попытаюсь понять, что говорят другие люди. Вера умирает последней...
Допустим, у нас есть суперкласс (называемый "Super") и подкласс (называемый "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();
выход "Супер", а не "Саб".
И если я позвоню:
Sub::get_title();
опять же, вывод "супер", и у меня даже есть $title, объявленный в Sub.
Таким образом, это означает, что когда я вызываю унаследованную статическую функцию, область действия функции будет суперклассом, а не вызываемым (даже если вы напечатаете обратную трассировку, это покажет, что вызов был выполнен в суперклассе!!!), и чтобы получить область видимости в качестве подкласса, на котором выполняется вызов, мне нужно переопределить этот метод внутри этого подкласса. Ну, этот вид поражает цель расширения классов, не так ли?
Итак, мой вопрос: могу ли я когда-нибудь расширить статический класс, вызвать один из унаследованных методов и получить область действия подкласса? или хотя бы чтобы можно было определить его имя класса? И если нет, то зачем мне расширять статические классы?
Спасибо!
3 ответа
Опять же, это невозможно до 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__;
}
}
Вы можете использовать get_called_class()
чтобы получить имя класса, который вы вызываете, даже если он статический. Вам не нужно нигде заявлять об этом.
Из примера Андрея:
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
Поэтому вам не нужно объявлять какие-либо переменные.
К счастью, я что-то делаю для себя, поэтому я сказал, прикрути это, я использую 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
Это может показаться немного грязным, но я не думаю, что это так плохо. После этого вы можете, наконец, расширить статические методы без необходимости повторного объявления методов.