Czym dokładnie są późne wiązania statyczne w PHP?

Czym właściwie są późne wiązania statyczne w PHP?

Author: Mark Amery, 2009-12-16

7 answers

Począwszy od PHP 5.3.0, PHP implementuje funkcję o nazwie late static binding, która może być używana do odwoływania się do wywołanej klasy w kontekście dziedziczenia statycznego.

Późne wiązanie statyczne próbuje rozwiązać to ograniczenie poprzez wprowadzenie słowa kluczowego, które odwołuje się do klasy, która została pierwotnie wywołana w czasie wykonywania. Zdecydowano się nie wprowadzać nowego słowa kluczowego, ale raczej użyć static, które było już zarezerwowane.

Zobaczmy przykład:

<?php
    class Car
    {
        public static function run()
        {
            return static::getName();
        }

        private static function getName()
        {
            return 'Car';
        }
    }

    class Toyota extends Car
    {
        public static function getName()
        {
            return 'Toyota';
        }
    }

    echo Car::run(); // Output: Car
    echo Toyota::run(); // Output: Toyota
?>

late static bindings praca przez przechowywanie klasy nazwane w ostatnim "non-forwarding call". W przypadku statycznych wywołań metod jest to klasa jawnie nazwana (Zwykle ta po lewej stronie operatora::); w przypadku niestatycznych wywołań metod jest to klasa obiektu.

"wywołanie przekierowujące" jest statycznym wywołaniem wprowadzanym przez self::, parent::, static::, lub, jeśli idzie w górę w hierarchii klasowej, forward_static_call().

Funkcja get_called_class() może być użyta do pobrania łańcucha z nazwą wywołanej klasy i static:: wprowadza jej zakres.

 73
Author: Mrinmoy Ghoshal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-18 18:07:26

Zdecydowanie musisz przeczytać późne wiązania statyczne w instrukcji PHP. Postaram się jednak krótko podsumować.

Zasadniczo sprowadza się to do tego, że słowo kluczowe self nie przestrzega tych samych zasad dziedziczenia. self zawsze rozwiązuje klasę, w której jest używana. Oznacza to, że jeśli utworzysz metodę w klasie rodzica i wywołasz ją z klasy potomnej, self nie będzie odwoływać się do dziecka tak, jak możesz się tego spodziewać.

Późne wiązanie statyczne wprowadza nowe użycie słowa kluczowego static, które odnosi się do tego konkretnego niedociągnięcia. Kiedy używasz static, reprezentuje klasę, w której po raz pierwszy jej używasz, tj. "wiąże" się z klasą runtime.

To są dwa podstawowe pojęcia stojące za tym. The way self, parent i static Działanie kiedy static jest w grze może być subtelne, więc zamiast wnikać bardziej szczegółowo, zdecydowanie zalecam przestudiowanie przykładów stron podręcznika. Gdy zrozumiesz podstawy każdego słowa kluczowego, przykłady są dość konieczne, aby zobaczyć, jakie wyniki masz zamiar uzyskać.

 172
Author: zombat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-13 12:57:41

Nie ma zbyt oczywistego zachowania:

Następujący kod tworzy "alphabeta".

class alpha {

    function classname(){
        return __CLASS__;
    }

    function selfname(){
        return self::classname();
    }

    function staticname(){
        return static::classname();
    }
}

class beta extends alpha {

    function classname(){
        return __CLASS__;
    }
}

$beta = new beta();
echo $beta->selfname(); // Output: alpha
echo $beta->staticname(); // Output: beta

Jeśli jednak usuniemy deklarację funkcji classname z klasy beta, otrzymamy 'alphaalpha' jako wynik.

 20
Author: Jokerius,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-15 13:20:58

Cytuję z książki: "PHP Master write cutting-edge code".

Późne wiązanie statyczne było funkcją wprowadzoną w php 5.3. Pozwala na nas do dziedziczenia metod statycznych z klasy nadrzędnej oraz do odwoływania się Klasa dziecięca.

Oznacza to, że możesz mieć klasę abstrakcyjną z metodami statycznymi i odwoływać się do konkretnych implementacji klasy dziecięcej za pomocą static:: method () notacja zamiast self:: method().

Zapraszam również do zapoznania się z oficjalną dokumentacją php: http://php.net/manual/en/language.oop5.late-static-bindings.php

Przykład:

<?php
class Animal {
    public static function StaticCall() {
        // Parent object invokes its own getAnimalName()
        // Child object invokes its own getAnimalName() instead of parent's getAnimalName()
        return static::getAnimalName(); 
    }

    public static function SelfCall() {
        return self::getWeight();
    }

    private static function getAnimalName(){
        return 'Animal <br />';
    }

    private static function getWeight(){
        return '10 kg <br />';
    }
}

class Bird extends Animal  {
    public static function getAnimalName(){
        return 'Bird <br />';
    }

    private static function getWeight(){
        return '2 kg <br />';
    }
}

echo Animal::StaticCall(); // Animal       
echo Animal::SelfCall();   // 10 kg        
echo Bird::StaticCall();   // Bird    invokes method from own object
echo Bird::SelfCall();     // 10 kg   invokes method from parent

W powyższym kodzie można zobaczyć dwie klasy Animal, która jest klasą nadrzędną i Bird, która jest klasą podrzędną. Zarówno Animal, jak i Bird mają metodę getAnimalName() i getWeight(). Klasa nadrzędna Animal ma dwie metody: StaticCall() i SelfCall().

Metoda StaticCall() wywołuje {[5] } za pomocą static słowo kluczowe.
Metoda SelfCall() wywołuje getWeight() za pomocą self słowo kluczowe.

Pytanie, które teraz mamy brzmi: w jakim kontekście getAnimalName() jest wykonywane?

Odpowiedź: static::getAnimalName() identyfikuje kontekst i wywołuje metodę w tym kontekście.

Jeśli wywołasz Bird::StaticCall() kod wykona StaticCall(), który znajduje się w Animal. Następnie static::getAnimalName() wywoła i wykona z Bird metodę getAnimalName().

Różni się to od self::, ponieważ self:: zawsze wywołuje metodę wewnątrz obiektu self zdefiniowanego w. Jeśli więc self::getWeight() jest zdefiniowany w obiekcie Animal w metodzie SelfCall() i zostanie wywołany Bird::SelfCall(), to self::getWeight() wywołuje getWeight() w kontekście obiektu Animal.

 10
Author: Julian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-13 12:23:16

Najprostszy przykład pokazujący różnicę.
Note, self::$C

class A
{
    static $c = 7;

    public static function getVal()
    {
        return self::$c;
    }
}

class B extends A
{
    static $c = 8;
}

B::getVal(); // 7

Late static binding, note static::$C

class A
{
    static $c = 7;

    public static function getVal()
    {
        return static::$c;
    }
}

class B extends A
{
    static $c = 8;
}

B::getVal(); // 8
 7
Author: Sergey Onishchenko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-23 12:00:43

Na przykład:

abstract class Builder {
    public static function build() {
        return new static;
    }
}

class Member extends Builder {
    public function who_am_i() {
         echo 'Member';
    }
}

Member::build()->who_am_i();
 4
Author: Petah,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-24 09:48:21

Patrząc na to z "Dlaczego miałbym tego używać?"perspektywa, to w zasadzie sposób na zmianę kontekstu, z którego statyczna metoda jest interpretowana/uruchamiana.

Z self, kontekst jest tym, w którym pierwotnie zdefiniowano metodę. Z static, to ten, z którego dzwonisz.

 4
Author: DanMan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-18 18:10:50