What exactly are late static bindings in PHP?

2019-01-03 01:31发布

What exactly are late static bindings in PHP?

7条回答
甜甜的少女心
2楼-- · 2019-01-03 01:42

The simplest example to show the difference.
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
查看更多
Melony?
3楼-- · 2019-01-03 01:50

I'm quoting from the book: "PHP Master write cutting-edge code".

Late static binding was a feature introduced with php 5.3. It allows us to inherit static methods from a parent class, and to reference the child class being called.

This means you can have an abstract class with static methods, and reference the child class's concrete implementations by using the static::method() notation instead of the self::method().

Feel free to take a look at the official php documentation as well: http://php.net/manual/en/language.oop5.late-static-bindings.php

Example:

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

In the code above you can see two classes Animal which is the parent class and Bird which is the child class. Both Animal and Bird have a getAnimalName() and getWeight() method. The superclass Animal has two methods: StaticCall() and SelfCall().

The method StaticCall() invokes getAnimalName() by using the static keyword.
The method SelfCall() invokes getWeight() by using the self keyword.

The question we now have is: in which context is getAnimalName() executed?

The answer: static::getAnimalName() identifies the context and invokes the method within that context.

If you invoke Bird::StaticCall() the code will execute StaticCall() which is in Animal. Then static::getAnimalName() will invoke and execute from Bird the method getAnimalName().

This differs from self::, because self:: always invokes the method within the object self is defined in. So if self::getWeight() is defined in object Animal in method SelfCall() and Bird::SelfCall() would be called then self::getWeight() invokes getWeight() in the context of the Animal object.

查看更多
成全新的幸福
4楼-- · 2019-01-03 01:52

There is not very obvious behavior:

The following code produces '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

However, if we remove the declaration of the classname function from the beta class, we get 'alphaalpha' as the result.

查看更多
一夜七次
5楼-- · 2019-01-03 02:00

For example:

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();
查看更多
6楼-- · 2019-01-03 02:02

As of PHP 5.3.0, PHP implements a feature called late static binding which can be used to reference the called class in the context of static inheritance.

Late static binding tries to solve that limitation by introducing a keyword that references the class that was initially called at runtime. It was decided not to introduce a new keyword, but rather use static that was already reserved.

Let's see an example:

<?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 work by storing the class named in the last "non-forwarding call". In case of static method calls, this is the class explicitly named (usually the one on the left of the :: operator); in case of non-static method calls, it is the class of the object.

A "forwarding call" is a static one that is introduced by self::, parent::, static::, or, if going up in the class hierarchy, forward_static_call().

The function get_called_class() can be used to retrieve a string with the name of the called class and static:: introduces its scope.

查看更多
We Are One
7楼-- · 2019-01-03 02:03

You definitely need to read Late Static Bindings in the PHP manual. However, I'll try to give you a quick summary.

Basically, it boils down to the fact that the self keyword does not follow the same rules of inheritance. self always resolves to the class in which it is used. This means that if you make a method in a parent class and call it from a child class, self will not reference the child as you might expect.

Late static binding introduces a new use for the static keyword, which addresses this particular shortcoming. When you use static, it represents the class where you first use it, ie. it 'binds' to the runtime class.

Those are the two basic concepts behind it. The way self, parent and static operate when static is in play can be subtle, so rather than go in to more detail, I'd strongly recommend that you study the manual page examples. Once you understand the basics of each keyword, the examples are quite necessary to see what kind of results you're going to get.

查看更多
登录 后发表回答