Что такое поздние статические привязки в PHP?

Что такое поздние статические привязки в PHP?

119 голосов | спросил Sarfraz 16 WedEurope/Moscow2009-12-16T10:17:32+03:00Europe/Moscow12bEurope/MoscowWed, 16 Dec 2009 10:17:32 +0300 2009, 10:17:32

7 ответов


0

Начиная с PHP 5.3.0, в PHP реализована функция, называемая поздним статическим связыванием, которая может использоваться для ссылки на вызываемый класс в контексте статического наследования.

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

Давайте посмотрим пример:

<?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 работает путем сохранения класса, указанного в последнем «вызове без переадресации». В случае статических вызовов методов это класс с явным именем (обычно слева от оператора ::); в случае нестатических вызовов методов это класс объекта.

«Переадресация вызова» - это статический вызов, который вводится self::, parent::, static:: или, если поднимется в иерархии классов, forward_static_call()

Функция get_called_class() может использоваться для извлечения строки с именем вызываемого класса и static:: представляет свою сферу.

ответил Mrinmoy Ghoshal 22 SatEurope/Moscow2012-12-22T11:10:34+04:00Europe/Moscow12bEurope/MoscowSat, 22 Dec 2012 11:10:34 +0400 2012, 11:10:34
0

Вам обязательно нужно прочитать поздние статические привязки в руководстве по PHP. Однако я постараюсь дать вам краткое резюме.

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

Позднее статическое связывание вводит новое использование для ключевого слова static, которое устраняет этот конкретный недостаток. Когда вы используете static, он представляет класс, в котором вы впервые его используете, т.е. он «привязывается» к классу времени выполнения.

Это две основные концепции. Способ self, parent и static работать, когда static в игре, может быть неуловимым Поэтому, вместо того чтобы вдаваться в подробности, я настоятельно рекомендую вам изучить примеры на странице руководства. Как только вы поймете основы каждого ключевого слова, примеры станут необходимыми, чтобы увидеть, какие результаты вы получите.

ответил zombat 16 WedEurope/Moscow2009-12-16T10:57:51+03:00Europe/Moscow12bEurope/MoscowWed, 16 Dec 2009 10:57:51 +0300 2009, 10:57:51
0

Там не очень очевидное поведение:

Следующий код производит '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

Однако, если мы удалим объявление функции classname из бета-класса, в результате мы получим «alphaalpha».

ответил Jokerius 19 22013vEurope/Moscow11bEurope/MoscowTue, 19 Nov 2013 18:06:02 +0400 2013, 18:06:02
0

Я цитирую из книги: «PHP Master напишу передовой код».

  

Позднее статическое связывание было добавлено в php 5.3. Это позволяет   нам наследовать статические методы от родительского класса, и ссылаться   вызываемый дочерний класс.

     

Это означает, что вы можете иметь абстрактный класс со статическими методами, и   ссылаться на конкретные реализации дочернего класса с помощью    static :: method () , вместо self :: method ().

Не стесняйтесь взглянуть и на официальную документацию php: http://php.net/manual/en/language. oop5.late-статического bindings.php

Пример:

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

В приведенном выше коде вы видите два класса Animal, который является родительским классом, и Bird который является дочерним классом. Оба Animal и Bird имеют getAnimalName() и метод getWeight(). Суперкласс Animal имеет два метода: StaticCall() и SelfCall().

Метод StaticCall() вызывает getAnimalName() используя    static.
Метод SelfCall() вызывает getWeight(), используя self    ключевое слово.

Теперь у нас есть вопрос: в каком контексте выполняется getAnimalName()?

Ответ: static::getAnimalName() идентифицирует контекст и вызывает метод в этом контексте.

По контексту мы говорим о родительском классе или дочернем классе. Если вы вызываете Bird::StaticCall() (дочерний класс), код выполнит унаследованный метод StaticCall() в Animal (родительский класс), затем static::getAnimalName() вызовет и выполнит метод getAnimalName() в Bird (дочерний класс).

Это отличается от self::, поскольку self:: всегда вызывает метод внутри объекта, в котором определен self. Так что если self::getWeight() определяется в объекте Animal в методе SelfCall() и Bird::SelfCall() будут вызваны тогда self::getWeight() вызывает getWeight() в контексте Animal объект.


Ключевое слово static используется в шаблоне разработки Singleton. Смотрите ссылку: https://refactoring.guru/design-patterns/singleton/php/example

ответил Jokerius 19 22013vEurope/Moscow11bEurope/MoscowTue, 19 Nov 2013 18:06:02 +0400 2013, 18:06:02
0

Самый простой пример, чтобы показать разницу.
Обратите внимание, self :: $ c

class A
{
    static $c = 7;

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

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

B::getVal(); // 7

Позднее статическое связывание, обратите внимание static :: $ c

class A
{
    static $c = 7;

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

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

B::getVal(); // 8
ответил Sergey Onishchenko 23 FebruaryEurope/MoscowbTue, 23 Feb 2016 15:00:43 +0300000000pmTue, 23 Feb 2016 15:00:43 +030016 2016, 15:00:43
0

Например:

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();
ответил Petah 9 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowThu, 09 Sep 2010 10:13:22 +0400 2010, 10:13:22
0

Глядя на это со слов "зачем мне это использовать?" в перспективе это в основном способ изменить контекст, из которого интерпретируется /запускается статический метод.

С self контекст является тем, где вы определили метод первоначально. С static это тот, с которого вы звоните.

ответил DanMan 13 PM00000030000005731 2015, 15:27:57

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132