PHP 中的后期静态绑定到底是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1912902/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What exactly are late static bindings in PHP?
提问by Sarfraz
What exactly are late static bindings in PHP?
PHP 中的后期静态绑定到底是什么?
回答by zombat
You definitely need to read Late Static Bindingsin the PHP manual. However, I'll try to give you a quick summary.
您肯定需要阅读PHP 手册中的后期静态绑定。不过,我会尽量给你一个快速的总结。
Basically, it boils down to the fact that the selfkeyword does not follow the same rules of inheritance. selfalways 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, selfwill not reference the child as you might expect.
基本上,它归结为self关键字不遵循相同的继承规则的事实。 self始终解析为使用它的类。这意味着如果您在父类中创建一个方法并从子类中调用它,self则不会像您期望的那样引用子类。
Late static binding introduces a new use for the statickeyword, 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.
后期静态绑定引入了static关键字的新用途,它解决了这个特殊的缺点。当您使用 时static,它代表您第一次使用它的类,即。它“绑定”到运行时类。
Those are the two basic concepts behind it. The way self, parentand staticoperate when staticis 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.
这是它背后的两个基本概念。的方式self,parent而static当操作static是在打法可以是细微的,因此而不是更详细的旅途中,我强烈建议你学习手册页的例子。一旦您了解了每个关键字的基础知识,这些示例对于了解您将获得什么样的结果是非常必要的。
回答by Mrinmoy Ghoshal
From PHP: Late Static Bindings - Manual:
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.
从 PHP 5.3.0 开始,PHP 实现了一个称为后期静态绑定的功能,可用于在静态继承的上下文中引用被调用的类。
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
staticthat was already reserved.
后期静态绑定试图通过引入一个关键字来解决这个限制,该关键字引用最初在运行时调用的类。... 决定不引入新关键字,而是使用
static已经保留的关键字。
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 byself::,parent::,static::, or, if going up in the class hierarchy,forward_static_call(). The functionget_called_class()can be used to retrieve a string with the name of the called class andstatic::introduces its scope.
后期静态绑定通过存储在最后一个“非转发调用”中命名的类来工作。在静态方法调用的情况下,这是显式命名的类(通常是
::运算符左侧的那个);在非静态方法调用的情况下,它是对象的类。“转发调用”是一种静态调用,由self::、parent::、static::、 或(如果在类层次结构中向上)引入forward_static_call()。该函数get_called_class()可用于检索具有被调用类名称的字符串并static::引入其作用域。
回答by Jokerius
There is not very obvious behavior:
没有很明显的行为:
The following code produces 'alphabeta'.
以下代码生成“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.
然而,如果我们从 beta 类中删除 classname 函数的声明,我们会得到 'alphaalpha' 作为结果。
回答by Julian
I'm quoting from the book: "PHP Master write cutting-edge code".
我引用了这本书:“PHP Master 编写尖端代码”。
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().
后期静态绑定是 php 5.3 引入的一个特性。它允许我们从父类继承静态方法,并引用被调用的子类。
这意味着您可以拥有一个带有静态方法的抽象类,并通过使用static::method()表示法而不是 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
也可以随意查看官方 php 文档:http: //php.net/manual/en/language.oop5.late-static-bindings.php
The clearest way to explain Late Static Binding is with a simple example. Take a look at the two class definitions below, and read on.
解释后期静态绑定最清晰的方法是用一个简单的例子。看看下面的两个类定义,然后继续阅读。
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";
}
}
We see a Parent Class (Vehicle) and a Child Class (Car). The Parent Class has 2 public methods:
我们看到一个父类(车辆)和一个子类(汽车)。父类有两个公共方法:
invokeDriveByStaticinvokeStopBySelf
invokeDriveByStaticinvokeStopBySelf
The Parent Class also has 2 private methods:
父类还有 2 个私有方法:
drivestop
drivestop
The Child Class overrides 2 methods:
子类覆盖了 2 个方法:
drivestop
drivestop
Now let's invoke the public methods:
现在让我们调用公共方法:
invokeDriveByStaticinvokeStopBySelf
invokeDriveByStaticinvokeStopBySelf
Ask yourself: Which class invokes invokeDriveByStatic/ invokeStopBySelf? The Parent or Child class?
问问自己:哪个类调用invokeDriveByStatic/ invokeStopBySelf?父类还是子类?
Take a look below:
看看下面:
// 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
The statickeyword is used in a Singleton design pattern.
See link: https://refactoring.guru/design-patterns/singleton/php/example
所述static关键字出现在Singleton设计图案中使用。见链接:https: //refactoring.guru/design-patterns/singleton/php/example
回答by Sergey Onishchenko
The simplest example to show the difference.
Note, self::$c
显示差异的最简单示例。
注意,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
后期静态绑定,注意static::$c
class A
{
static $c = 7;
public static function getVal()
{
return static::$c;
}
}
class B extends A
{
static $c = 8;
}
B::getVal(); // 8
回答by Petah
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();
回答by DanMan
Looking at it from a "why would I use this?" perspective, it's basically a way to change the context from which the static method is being interpreted/run.
从“我为什么要使用这个?”的角度来看它。从角度来看,它基本上是一种改变静态方法被解释/运行的上下文的方法。
With self, the context is the one where you defined the method originally. With static, it's the one you're calling it from.
使用self,上下文是您最初定义方法的地方。使用static,它是您从中调用它的那个。
回答by Frank Forte
Also, watch if you update static variables in child classes. I found this (somewhat) unexpected result where child B updates child C:
另外,请注意是否更新子类中的静态变量。我发现这个(有点)意外的结果是子 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
// )
You can fix it by declaring the same variable in each child class, for example:
您可以通过在每个子类中声明相同的变量来修复它,例如:
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;
}
}

