究竟是什么迟到静态的绑定在PHP?
-
19-09-2019 - |
题
究竟是什么迟到静态的绑定在PHP?
解决方案
您一定要阅读晚静态绑定表 PHP手册。不过,我会尽量给你一个简单的总结。
基本上,它归结为一个事实,即self
关键字不遵循继承相同的规则。 self
始终解析其所使用的类。这意味着,如果您在父类的方法,并从一个子类调用它,self
不会引用子如您所想。
晚期静态绑定引入了对static
关键字,它解决了这个特定的缺点的新用途。当您使用static
,它代表的类在您第一次使用它,即。它结合“到运行时类。
这些是其背后的两个基本概念。当self
在比赛可能是细微,因此而不是去到更详细的方式parent
,static
和static
工作,我强烈建议你学习手册页的例子。一旦你了解了每一关键字的基础知识,例子就看你会得到什么样的结果相当必要的。
其他提示
自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::
介绍了它的范围。
有不是很明显的行为:
下面的代码产生 '的Alpha-Beta'。
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
然而,如果我们要从所述β-类类名函数的声明,我们得到“alphaalpha”作为结果。
我引用的书:"PHP主写沿代码"。
晚静态的结合是一个要素引入php5.3.它允许 我们继承静态的方法从父类,并参考 该子类。
这意味着你可以拥有一个抽象的类的静态的方法, 参考儿童级的具体实施通过使用 静态的方法() 符号,而不是自::方法().
随时来看看官方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";
}
}
我们看到一个父类(车辆)和儿童课(车)。父类拥有2公共方法:
invokeDriveByStatic
invokeStopBySelf
父类还有2个私人方法:
drive
stop
这类儿童的复盖2方法:
drive
stop
现在,让我们援引公共的方法:
invokeDriveByStatic
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
关键词是用于单独的设计图案。见链接: https://refactoring.guru/design-patterns/singleton/php/example
最简单的例子以示区别。结果 请注意,自:: $ 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
例如:
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();
看它从一个“我为什么会用这个?”的角度来看,它基本上以改变从该静态方法被解释/运行的上下文的方法。
通过self
,上下文是其中最初定义的方法之一。随着static
,这是你从调用它的一个。
另外,看,如果你在子类中更新静态变量。我发现这个(有点)出乎意料的结果,其中小孩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
// )
可以通过在每个子类声明相同的变量解决它,例如:
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;
}
}