PHP中的后期静态绑定到底是什么?

PHP中的后期静态绑定到底是什么?,php,late-binding,late-static-binding,Php,Late Binding,Late Static Binding,什么是PHP中最新的静态绑定?您肯定需要阅读PHP手册。不过,我会给你一个简短的总结 基本上,它归结为这样一个事实:self关键字不遵循相同的继承规则self始终解析为使用它的类。这意味着,如果在父类中创建一个方法并从子类调用它,self将不会像预期的那样引用子类 后期静态绑定引入了static关键字的新用法,它解决了这个特殊的缺点。当您使用static时,它表示您第一次使用它的类,即它“绑定”到运行时类 这是它背后的两个基本概念。self、parent和static在static起作用时的操作

什么是PHP中最新的静态绑定?

您肯定需要阅读PHP手册。不过,我会给你一个简短的总结

基本上,它归结为这样一个事实:
self
关键字不遵循相同的继承规则
self
始终解析为使用它的类。这意味着,如果在父类中创建一个方法并从子类调用它,
self
将不会像预期的那样引用子类

后期静态绑定引入了
static
关键字的新用法,它解决了这个特殊的缺点。当您使用
static
时,它表示您第一次使用它的类,即它“绑定”到运行时类

这是它背后的两个基本概念。
self
parent
static
static
起作用时的操作方式可能很微妙,因此我强烈建议您研究手册页面的示例,而不是更详细。一旦您了解了每个关键字的基本知识,就需要通过示例了解您将获得什么样的结果。

例如:

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();
class C extends A{
    protected static $things; // add this and B will not interfere!

    public static function things(){
        static::$things[2] = 'Thing C';
        return static::$things;        
    }
}
发件人:

从PHP5.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
?>

后期静态绑定通过存储上次“非转发调用”中命名的类来工作。对于静态方法调用,这是显式命名的类(通常是
运算符左侧的类);对于非静态方法调用,它是对象的类。“转发调用”是由
self:
父级:
静态::
引入的静态调用,或者,如果在类层次结构中向上,则是
转发静态调用()
。函数
get\u called\u class()
可用于检索具有被调用类名称的字符串,并且
static::
介绍了其作用域


没有非常明显的行为:

下面的代码生成“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

但是,如果我们从beta类中删除classname函数的声明,我们会得到“alphaalpha”。

我引用了《PHP大师编写尖端代码》一书中的话

后期静态绑定是PHP5.3引入的一个特性。它允许 我们从父类继承静态方法,并引用 正在调用的子类

这意味着您可以拥有一个带有静态方法的抽象类,并且 通过使用 static::method()表示法,而不是self::method()

也可以随意查看php官方文档:


解释后期静态绑定最清晰的方法是使用一个简单的示例。看看下面的两个类定义,然后继续阅读

class Vehicle {
    public static function invokeDriveByStatic() {
        return static::drive(); // Late Static Binding
    }
    public static function invokeStopBySelf() {
        return self::stop(); // NOT Late Static Binding
    }
    private static function drive(){
        return "I'm driving a VEHICLE";
    }
    private static function stop(){
        return "I'm stopping a VEHICLE";
    }
}

class Car extends Vehicle  {
    protected static function drive(){
        return "I'm driving a CAR";
    }
    private static function stop(){
        return "I'm stopping a CAR";
    }
}
我们看到一个父类(车辆)和一个子类(汽车)。 父类有2个公共方法:

  • invokedDriveByStatic
  • invokeStopBySelf
父类还有2个私有方法:

  • 驱动器
  • 停止
子类重写2个方法:

  • 驱动器
  • 停止
现在让我们调用公共方法:

  • invokedDriveByStatic
  • invokeStopBySelf
问问自己:哪个类调用
invokeDriveByStatic
/
invokeStopBySelf
?父类还是子类

请看下面:

// This is NOT Late Static Binding
// Parent class invokes from Parent. In this case Vehicle.
echo Vehicle::invokeDriveByStatic(); // I'm driving a VEHICLE
echo Vehicle::invokeStopBySelf(); // I'm stopping a VEHICLE

// !!! This is Late Static Binding !!!!
// Child class invokes an inherited method from Parent.
// Child class = Car, Inherited method = invokeDriveByStatic().
// The inherited method invokes a method that is overridden by the Child class.
// Overridden method = drive()
echo Car::invokeDriveByStatic(); // I'm driving a CAR

// This is NOT Late Static Binding
// Child class invokes an inherited method from Parent.
// The inherited method invokes a method inside the Vehicle context.
echo Car::invokeStopBySelf(); // I'm stopping a VEHICLE

static
关键字用于单例设计模式。 请参阅链接:

从“我为什么要使用它?”的角度来看,它基本上是一种改变解释/运行静态方法的上下文的方法


使用
self
,上下文就是您最初定义方法的上下文。使用
static
,您可以从中调用它。

这是显示差异的最简单示例。
注意,self::$c

class A
{
    static $c = 7;

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

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

B::getVal(); // 7
后期静态绑定,注意静态::$c

class A
{
    static $c = 7;

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

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

B::getVal(); // 8

此外,还要注意是否更新子类中的静态变量。我发现子B更新子C时出现了(有些)意外的结果:

class A{
    protected static $things;
}

class B extends A {
    public static function things(){
        static::$things[1] = 'Thing B';
        return static::$things; 
    }
}

class C extends A{
    public static function things(){
        static::$things[2] = 'Thing C';
        return static::$things;        
    }
}

print_r(C::things());
// Array (
//   [2] => Thing C
// )

B::things();

print_r(C::things()); 
// Array (
//    [2] => Thing C
//    [1] => Thing B
// )
您可以通过在每个子类中声明相同的变量来修复它,例如:

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();
class C extends A{
    protected static $things; // add this and B will not interfere!

    public static function things(){
        static::$things[2] = 'Thing C';
        return static::$things;        
    }
}

很不错的。PHP手册中也显示了同样的内容,但这要清楚得多。参考:(见例4)我发现这篇文章真的很有用,很有描述性,请查看[link]()这篇文章是一篇没有引用标记的文章的80%的逐字复制。