Pytanie Dziedzicz właściwości statyczne w podklasie bez redeclaracji?


Mam taki sam problem jak ten facet z aplikacją, którą piszę teraz. Problem polega na tym, że właściwości statyczne nie są dziedziczone w podklasach, więc jeśli użyję słowa kluczowego static :: w mojej głównej klasie, to ustawię zmienną również w mojej głównej klasie.

Działa, jeśli zmienię parametry statyczne w mojej podklasie, ale spodziewam się dużej liczby statycznych właściwości i podklas i chcę uniknąć duplikowania kodu. Najwyżej oceniona odpowiedź na stronie, którą podjąłem, zawiera link do kilku "obejść", ale wydaje się, że miała 404'd. Czy ktoś może mi pomóc lub może skierować mnie w kierunku wspomnianych obejść?


12
2018-05-01 22:11


pochodzenie




Odpowiedzi:


Nie jestem pewien, o jakie konkretnie rozwiązanie chodzi, mogę myśleć o kilku, które mogą zadziałać. Osobiście nie użyłbym ich w żadnym kodzie. Radzę ci spojrzeć Czy możliwe jest nadużywanie późnego wiązania statycznego w PHP? i zastanowić się, czy istnieje lepszy sposób na zrobienie tego, co ma nadzieję osiągnąć.

Pamiętaj też, że mój kod jest całkowicie nieprzetestowany, ponieważ napisałem go właśnie tutaj.

Metoda 1: Zawsze używaj tablicy do obliczenia

Wszystkie inne metody są oparte na tym. Niezależnie od tego, czy użyjesz właściwości statycznej, wstawisz kod, aby wykryć klasę i ją pobrać. Zastanowiłbym się tylko, czy nigdy nie planujesz korzystać z nieruchomości w innym miejscu.

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

Metoda 2: Użyj metod getter / setting

Jeśli planujesz używać go w więcej niż jednym miejscu, ta metoda byłaby lepsza. Niektóre wzorce singletonowe używają podobnej metody.

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

Metoda 3: __callStatic

Jest to zdecydowanie najwygodniejsza metoda. Jednak musisz użyć instancji obiektu, aby z niej skorzystać (__get i __set nie mogą być używane statycznie). Jest to również najwolniejsza metoda (znacznie wolniejsza od pozostałych dwóch). Zgaduję, że skoro już używasz właściwości statycznych, to już nie możesz tego zrobić. (Jeśli ta metoda działa dla ciebie, prawdopodobnie byłoby lepiej, gdybyś nie używał właściwości statycznych)

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

6
2018-05-02 16:02



Metoda 1 jest tym, czego szukałem. - M K


Aby przejść nieco dalej niż odpowiedź Reece45, możesz użyć poniższej metody, aby uzyskać wartość swojej tablicy.

<?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, ) 

0
2017-12-04 23:41