2009-12-16 24 views

回答

67

作为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::介绍其作用域。

158

您肯定需要在PHP手册中阅读Late Static Bindings。不过,我会尽力给你一个快速总结。

基本上,归结为self关键字不符合继承规则。 self始终解决使用它的类。这意味着如果您在父类中创建一个方法并从子类调用该方法,那么self将不会像您期望的那样引用该孩子。

延迟静态绑定为static关键字引入了新的用法,它解决了这个特定的缺点。当您使用static时,它代表您首次使用它的类,即。它'绑定'到运行时类。

这是背后的两个基本概念。 self,和staticstatic在场时可以微妙的操作,所以我不强烈建议你学习手册页的例子。一旦你了解了每个关键词的基础知识,这些例子就非常有必要了解你将得到什么样的结果。

+24

+1您的描述比在PHP中发现简单明了手册。 – Mouli 2013-10-29 05:40:13

+2

这应该是公认的答案。它更简单和有帮助 – 2017-10-20 21:13:17

+0

我发现这篇文章非常有用和描述性,请查看[链接](https://www.techflirt.com/tutorials/oop-in-php/late-static-binding.html) – 2017-10-20 21:26:15

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'。但是,如果我们从beta类中删除了classname函数的声明,那么我们会得到'alphaalpha'作为结果。

+1

这很有趣。我不得不检查自己 – instead 2014-05-28 17:40:51

+1

非常好。 PHP手册中也显示了相同的内容,但这更清晰。作为参考:http://php.net/manual/en/language.oop5.late-static-bindings.php(见例4) – musicin3d 2016-05-02 16:53:20

9

我在引用这本书:“PHP大师写尖端代码”。

延迟静态绑定是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这是孩子班。 AnimalBird都有getAnimalName()getWeight()方法。超类Animal有两种方法:StaticCall()SelfCall()

方法StaticCall()通过使用 static关键字来调用getAnimalName()
方法SelfCall()通过使用self 关键字来调用getWeight()

我们现在的问题是:其中上下文是getAnimalName()执行?

答案:static::getAnimalName()标识上下文并调用该上下文中的方法。

如果您调用Bird::StaticCall()代码将执行StaticCall()这是Animal。然后static::getAnimalName()将调用并执行Bird方法getAnimalName()

这不同于self::,因为self::总是调用对象self内的方法中所定义,因此,如果self::getWeight()在对象Animal被定义在方法SelfCall()Bird::SelfCall()将被称为然后self::getWeight()Animal对象的上下文调用getWeight()

4

从“为什么我会用这个?”看它。透视,它基本上是一种改变静态方法被解释/运行的环境的方式。

对于self,上下文是最初定义方法的地方。与static,这是你打电话给它的人。

7

最简单的示例来显示区别。
注意,自:: $ 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