zom*_*bat 190

你肯定需要在PHP手册中阅读Late Static Bindings.但是,我会尽量给你一个快速摘要.

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

后期静态绑定引入了static关键字的新用途,它解决了这个特殊的缺点.使用时static,它代表您首次使用它的类,即.它"绑定"到运行时类.

这是它背后的两个基本概念.这种方式self,parent以及在播放static时的操作static可能是微妙的,所以我强烈建议您学习手册页示例,而不是详细介绍.一旦理解了每个关键字的基础知识,就可以通过这些示例来了解您将获得哪种结果.

  • +1您的描述比PHP手册中的描述简单明了. (27认同)
  • 这应该是公认的答案.它更简单,更有帮助 (2认同)

Mri*_*hal 80

从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
?>
Run Code Online (Sandbox Code Playgroud)

late static bindings通过存储在最后一次"非转发呼叫"中命名的类来工作.在静态方法调用的情况下,这是显式命名的类(通常是::运算符左侧的类); 在非静态方法调用的情况下,它是对象的类.

A"转发呼叫"是通过引入一个静态self::,parent::,static::,或者,如果在类层次结构往上走,forward_static_call().

该函数get_called_class()可用于检索具有被调用类名称的字符串并static::引入其范围.

  • 这篇文章的 80% 是 [php.net 文章](https://php.net/manual/en/language.oop5.late-static-bindings.php) 的逐字副本,没有引用标记。 (2认同)

Jok*_*ius 22

行为不是很明显:

以下代码生成'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
Run Code Online (Sandbox Code Playgroud)

但是,如果我们从beta类中删除classname函数的声明,我们会得到'alphaalpha'作为结果.

  • 非常好。PHP 手册中也显示了相同的内容,但这要清晰得多。供参考:http://php.net/manual/en/language.oop5.late-static-bindings.php(见例 4) (2认同)

Jul*_*ian 10

我引用了这本书:"PHP Master写的尖端代码".

后期静态绑定是php 5.3引入的一个功能.它允许我们从父类继承静态方法,并引用被调用的子类.

这意味着您可以使用静态方法创建一个抽象类,并使用static :: method()表示法而不是self :: method()来引用子类的具体实现 .

请随意查看官方php文档:http: //php.net/manual/en/language.oop5.late-static-bindings.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";
    }
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,您可以看到两个类invokeDriveByStatic,即父类,invokeStopBySelf它是子类.双方drivestop有一个drivestop方法.超类invokeDriveByStatic有两种方法:invokeStopBySelfinvokeDriveByStatic.

该方法使用 关键字invokeStopBySelf调用. 该方法使用 关键字调用.staticinvokeDriveByStatic
invokeStopBySelfdrivestop

问题:drive执行哪个上下文?

答案:stop标识上下文并在该上下文中调用方法.

通过上下文,我们讨论的是父类或子类.如果调用invokeDriveByStatic(子类)的代码将执行继承的方法invokeStopBySelfinvokeDriveByStatic(父类),然后invokeStopBySelf将调用和执行方法staticinvokeDriveByStatic(子类).

这不同于invokeStopBySelf,因为drive总是调用对象内的方法stop是在所定义.因此,如果drive在对象被定义stop在方法invokeDriveByStaticinvokeStopBySelf将被称为然后invokeDriveByStatic调用invokeStopBySelf在的上下文static对象.


invokeDriveByStatic关键字用于Singleton设计模式.请参见链接:https://refactoring.guru/design-patterns/singleton/php/example


Dan*_*Man 7

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

使用self,上下文是您最初定义方法的地方。使用static,它是您从中调用它的那个。


Ser*_*nko 7

显示差异的最简单示例.
注意,自我:: $ c

class A
{
    static $c = 7;

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

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

B::getVal(); // 7
Run Code Online (Sandbox Code Playgroud)

后期静态绑定,请注意静态:: $ c

class A
{
    static $c = 7;

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

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

B::getVal(); // 8
Run Code Online (Sandbox Code Playgroud)


Pet*_*tah 5

例如:

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();
Run Code Online (Sandbox Code Playgroud)