2009-12-16 7 views

ответ

67

В РНР 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:: представляет ее область действия.

158

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

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

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

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

+24

+1 Ваше описание прост и понятен, чем та, что в PHP руководство. – Mouli

+2

Это должен быть принятый ответ. это проще и полезно –

+0

Я нашел эту статью очень полезной и описательной, проверьте ее [link] (https://www.techflirt.com/tutorials/oop-in-php/late-static-binding.html) –

4

Например:

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(); 
20

Существует не очень очевидное поведение:

Следующий код создает '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» в качестве результата.

+1

Это интересно , Я должен был проверить себя – instead

+1

Очень приятно. То же самое показано в руководстве по PHP, но это намного яснее. Для справки: http://php.net/manual/en/language.oop5.late-static-bindings.php (см. Пример 4) – musicin3d

9

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

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

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

Вы можете посмотреть на официальной документации PHP, а также: http://php.net/manual/en/language.oop5.late-static-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() будет вызывать и выполнять от Bird метод getAnimalName().

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

4

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

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

7

Простейший пример, чтобы показать разницу.
Примечание, самостоятельно :: $ с

class A 
{ 
    static $c = 7; 

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

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

B::getVal(); // 7 

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

class A 
{ 
    static $c = 7; 

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

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

B::getVal(); // 8 
Смежные вопросы