У меня такая же проблема, как у этого парня с приложением, которое я пишу прямо сейчас. Проблема в том, что статические свойства не наследуются в подклассах, поэтому, если я использую static-ключевое слово в моем основном классе, он также устанавливает переменную в моем основном классе.
Он работает, если я переопределяю статические переменные в моем подклассе, но я ожидаю, что у меня будет большое количество статических свойств и подклассов и вы захотите избежать дублирования кода. Самый высокий рейтинг на странице, с которой я связан, имеет ссылку на несколько «обходных решений», но, похоже, он имеет 404'd. Может ли кто-нибудь оказать мне помощь или, возможно, указать мне в сторону упомянутых обходных решений?
Я не знаю, о каком конкретном обходном пути речь шла, я могу придумать немало, которые могут работать. Я лично не буду использовать их в любом коде. Я бы порекомендовал вам взглянуть. Можно ли злоупотреблять поздним статическим привязкой в PHP? и переосмыслить, если есть лучший способ сделать то, что вы надеетесь достичь.
Также имейте в виду, что мой код полностью непроверен, поскольку я написал его только здесь.
Все остальные методы основаны на этом. В Whereever вы используете статическое свойство, вы вставляете код, чтобы определить класс и получить его. Я бы рассматривал это только в том случае, если вы никогда не планируете использовать свойство где-либо еще.
$class = get_called_class(); if(isset(self::$_names[$class])) { return self::$_names[$class]; } else { return static::NAME_DEFAULT; }
Если вы планируете использовать его в нескольких местах, этот метод будет лучше. Некоторые синглтонные шаблоны используют аналогичный метод.
<?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; } }
Это, безусловно, самый удобный метод. Однако вам нужно иметь экземпляр объекта для его использования (__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; } } }
Чтобы идти немного дальше ответа 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, )