Расширение статических классов 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

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

Другие вопросы по тегам