Унаследовать статические свойства в подклассе без переопределения? - PullRequest
12 голосов
/ 02 мая 2010

У меня та же проблема, что и у этого парня с приложением, которое я сейчас пишу. Проблема в том, что статические свойства не наследуются в подклассах, и поэтому, если я использую ключевое слово static :: в моем основном классе, оно также устанавливает переменную в моем основном классе.

Это работает, если я повторно объявлю статические переменные в моем подклассе, но я ожидаю, что у меня будет большое количество статических свойств и подклассов, и хочу избежать дублирования кода. Ответ с самым высоким рейтингом на странице, на которую я ссылался, содержит ссылку на несколько «обходных путей», но, похоже, имеет 404. Может ли кто-нибудь оказать мне какую-то помощь или, возможно, направить меня в направлении указанных обходных путей?

Ответы [ 2 ]

6 голосов
/ 02 мая 2010

Я не уверен, о каком конкретном обходном пути идет речь, я могу вспомнить немало, которые могут сработать. Я лично не использовал бы их в любом коде. Я бы порекомендовал вам взглянуть Можно ли чрезмерно использовать позднее статическое связывание в PHP? и переосмыслить, если есть лучший способ сделать то, что вы надеетесь достичь.

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

Способ 1: всегда использовать массив для рисунка

Все остальные методы основаны на этом. Где бы вы ни использовали статическое свойство, вы вставляете код, чтобы определить класс и получить его. Я хотел бы рассмотреть это, только если вы никогда не планируете использовать собственность где-либо еще.

$class = get_called_class();
if(isset(self::$_names[$class])) {
    return self::$_names[$class];
}
else {
    return static::NAME_DEFAULT;
}

Метод 2: Использование методов получения / настройки

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

<?php
class SomeParent {
    const NAME_DEFAULT = 'Whatever defaults here';

    private static $_names = array();

    static function getName($property) {
        $class = get_called_class();
        if(isset(self::$_names[$class])) {
            $name self::$_names[$class];
        }
        else {
            $name = "Kandy"; // use some sort of default value
        }
    }

    static function setName($value) {
        $class = get_called_class();
        self::$_names[$class] = $value;
    }
}

Метод 3: __callStatic

Это, безусловно, самый удобный метод. Однако для его использования необходим экземпляр объекта (__get и __set не могут использоваться статически). Это также самый медленный метод (намного медленнее, чем два других). Я предполагаю, что, поскольку вы уже используете статические свойства, это уже не вариант. (Если этот метод работает для вас, было бы лучше, если бы вы не использовали статические свойства)

<?php
class SomeParent {

    const NAME_DEFAULT = 'Whatever defaults here';

    private static $_names = array();

    function __get($property) {
        if($property == 'name') {
            $class = get_called_class();
            if(isset(self::$_names[$class])) {
                return self::$_names[$class];
            }
            else {
                return static::NAME_DEFAULT;
            }
        }
        // should probably trigger some sort of error here
    }

    function __set($property, $value) {
        if($property == 'name') {
            $class = get_called_class();
            self::$_names[$class] = $value;
        }
        else {
            static::$property = $value;
        }
    }
}
0 голосов
/ 05 декабря 2015

Чтобы пойти немного дальше, чем ответ Reece45, вы можете использовать следующий метод, чтобы получить значение вашего массива.

<?php
class MyParent {
    public static $config = array('a' => 1, 'b' => 2);

    public static function getConfig() {
        $ret = array();
        $c = get_called_class();
        do {
            $ret = array_merge($c::$config, $ret);
        } while(($c = get_parent_class($c)) !== false);
        return $ret;
    }
}

class MyChild extends MyParent {
    public static $config = array('a' => 5, 'c' => 3, 'd' => 4);
    public function myMethod($config) {
        $config = array_merge(self::getConfig(), $config);
    }
}

class SubChild extends MyChild {
    public static $config = array('e' => 7);
}

var_export(MyChild::getConfig());
// result: array ( 'a' => 5, 'b' => 2, 'c' => 3, 'd' => 4, )

$mc = new MyChild();
var_export($mc->myMethod(array('b' => 6)));
// result: array ( 'a' => 5, 'b' => 6, 'c' => 3, 'd' => 4, )

var_export(SubChild::getConfig());
// result: array ( 'a' => 5, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 7, ) 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...