Наследование статических членов в PHP

В PHP, если статический атрибут определен в родительском классе, он не может быть переопределен в дочернем классе. Но мне интересно, есть ли что-то в этом роде.

Я пытаюсь написать обертку для чужой (несколько неуклюжей) функции. Эта функция может применяться к множеству разных типов данных, но для каждого из них требуются разные флаги и опции. Но 99% времени, по умолчанию для каждого типа было бы достаточно.

Было бы неплохо, если бы это можно было сделать с наследованием, без необходимости писать новые функции каждый раз. Например:

class Foo { public static $default = 'DEFAULT'; public static function doSomething ($param = FALSE ) { $param = ($param === FALSE) ? self::$default : $param; return $param; } } class Bar extends Foo { public static $default = 'NEW DEFAULT FOR CHILD CLASS'; } echo Foo::doSomething() . "\n"; // echoes 'DEFAULT' echo Bar::doSomething() . "\n"; // echoes 'DEFAULT' not 'NEW DEFAULT FOR CHILD CLASS' // because it references $default in the parent class :( 

Классический пример того, почему использование статистики как глобальных (функции в этом случае) – плохая идея независимо от языка.

Наиболее надежным методом является создание нескольких подэлементов реализации абстрактного базового класса «Действие».

Затем, чтобы попытаться устранить некоторую досаду о том, чтобы создать экземпляр класса только для вызова его методов, вы можете обернуть его на какой-нибудь фабрике.

Например:

 abstract class AbstractAction { public abstract function do(); } class FooAction extends AbstractAction { public function do() { echo "Do Foo Action"; } } class BarAction extends AbstractAction { public function do() { echo "Do Bar Action"; } } 

Затем создайте фабрику для «помощи» при создании функции

 class ActionFactory { public static function get($action_name) { //... return AbstractAction instance here } } 

Затем используйте его как:

 ActionFactory::get('foo')->do(); 

Предстоящая версия PHP 5.3.0 включает в себя позднюю статическую привязку , которая может помочь. Используя эту функцию, вы можете использовать статическую переменную внутри статического метода, и пусть поздняя статическая привязка позаботится о поиске «правильного» метода.

 class Foo { public static function getDefault() { static $default = 'DEFAULT'; return $default; } public static function doSomething ($param) { $default=static::getDefault(); // here is the late static binding $param = ($param === FALSE) ? $default : $param; return $param; } } class Bar extends Foo { public static function getDefault() { static $default = 'NEW DEFAULT FOR CHILD CLASS'; return $default; } } 

На самом деле, я думаю, что это не так: вы можете ovverride статические propeties (для этого вам нужно> = 5.3 PHP ). Но вы должны быть осторожны при переопределении этого статического свойства (и это ошибка в исходном коде)

Вам нужно использовать static :: $ myStaticProperty вместо использования self :: $ myStaticProperty

self :: будет ссылаться на текущий класс, поэтому, если вы находитесь внутри унаследованного статического метода, это будет refrence статическое свойство этого класса, определяющего этот метод! При использовании ссылочного ключевого слова static :: будет действовать как $ this – когда вы используете методы / propeties экземпляра.

doSomething () – унаследованный статический метод в классе Bar в вашем примере. Поскольку вы использовали self :: there, он ссылается на статическое свойство класса Foo. Вот почему вы не заметили разницы … Попробуйте изменить self :: to static :: !

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

 class A { // a static property - we will test override with it protected static $var = 'class A var - override'; // a static property - we will test value overwrite with it protected static $var2 = 'class A var2 - value overwrite'; public static function myStaticOverridePropertyTest() { return static::$var; } public static function myStaticValueOverwritePropertyTest() { return static::$var2; } /** * This method is defined only here - class B will inherit this one! * We use it to test the difference btw self:: and static:: * * @return string */ public static function myStaticMethodTest() { //return self::getValue(); return static::getValue(); } /** * This method will be overwritten in class B * @return string */ protected static function getValue() { return 'value from class A'; } } class B extends A { // we override this inherited static property protected static $var = 'class B var - override'; /** * This method is overwritten from class A * @return string */ protected static function getValue() { return 'value from class B'; } /** * We modify the value of the inherited $var2 static property */ public static function modStaticProperty() { self::$var2 = 'class B - altered value! - value overwrite'; } } echo ("-- testing class A:\n"); echo (A::myStaticOverridePropertyTest(). "\n"); echo (A::myStaticValueOverwritePropertyTest(). "\n"); echo (A::myStaticMethodTest(). "\n"); echo ("-- now testing class B:\n"); echo (B::myStaticOverridePropertyTest(). "\n"); echo (B::myStaticValueOverwritePropertyTest(). "\n"); echo (" now invoking B::modStaticProperty() .\n"); B::modStaticProperty(); echo (B::myStaticValueOverwritePropertyTest(). "\n"); echo ("-- now re-testing class A:\n"); echo (A::myStaticOverridePropertyTest(). "\n"); echo (A::myStaticValueOverwritePropertyTest(). "\n"); echo (A::myStaticMethodTest(). "\n"); 

Это приведет к выводу:

– класс тестирования A:
класс var varride
класс A var2 – значение переписать
значение из класса A
– теперь тестирование класса B:
класс B var – override
класс A var2 – значение переписать
теперь вызывается B :: modStaticProperty () …
класс B – измененное значение! – переписать значение
– теперь повторное тестирование класса A:
класс var varride
класс B – измененное значение! – переписать значение
значение из класса A

И вот мы здесь, вы можете увидеть разницу между переопределенными и только перезаписанными статическими свойствами … посмотрите строку вывода, выделенную полужирным шрифтом! Когда мы вызывали modStaticProperty () класса B, он также менял значение этой статической переменной в классе A. Поскольку это статическое свойство было унаследовано и не было переоценено! Думаю об этом…