Подтвердить что ты не робот

Наследовать статические свойства в подклассе без повторной декларации?

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

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

4b9b3361

Ответ 1

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

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

Способ 1. Всегда используйте массив для отображения

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

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

Способ 2: Используйте методы getter/setting

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

<?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;
        }
    }
}

Ответ 2

Чтобы идти немного дальше, чем 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, )