为什么$this关键字在static中出现致命错误,但(new self)工作正常


class A {
public $a = "BooMBa";
public function fun1() {
echo $this->a; 
// echo (new self)->a;
}
}
class B extends A {
public static function fun2() {
return (new self)->fun1();
// return static::fun1();
}
}
B::fun2();  // returns BooMBa

如果我将fun2()更改为return static::fun1(),则会出现"致命错误:不在对象上下文中时使用$this"。但如果我将fun1更改为echo (new self)->a;,则工作正常
有人能解释为什么static::讨厌$this而不讨厌(new self)

附言:请考虑一下,我已经完成了以下给出的问答;一些章节和更多的文章还无法准确地了解这个特定的场景,以及正在发生的事情。
什么是new self();PHP中的意思
PHP:new self和new object的区别()
PHP:The Basics Manual
在PHP中,self和$this之间有什么区别?

PPS:这个问答;PHP致命错误:不在对象上下文中使用$this与我的无关,除了相同的错误消息。这是完全不同的背景。在这个问题中,他只是静态地调用一个非静态方法。同时,由于后期的静态绑定和关键字(new self),我的问题更加复杂。用上面提到的问答中的答案根本不可能理解我的问题;A所以请仔细阅读这两个问答;A,然后将其标记为重复。非常感谢。

这个问题涉及到"类和实例之间的区别是什么"。

我将简化你的例子,循序渐进。

class A {
public $a = "BooMBa";
public function fun1() {
echo $this->a; 
}
public static function fun2() {
return (new self)->fun1();
}
}
A::fun2();  // returns BooMBa
  1. A::func2()-对A::func2的静态调用
  2. (new self)->fun1()-创建A的实例并调用该实例的fun1
  3. echo $this->a-当前实例(步骤2中创建)的a的echo内容

A::func2的每次调用都会在步骤2 中创建A的新实例


class A {
public $a = "BooMBa";
public function fun1() {
echo $this->a; 
}
public static function fun2() {
return static::fun1();
}
}
A::fun2();  // fails
  1. A::func2()-对A::func2的静态调用
  2. static::fun1()-对A::func1的静态调用,没有实例。AFAIK这应该会生成警告,因为您对实例方法进行了静态调用
  3. echo $this->a;-回显当前实例的a的内容,但由于我们是从静态调用来到这里的,所以没有实例,我们在类范围内。错误

class A {
public $a = "BooMBa";
public function fun1() {
echo (new self)->a;
}
public static function fun2() {
return static::fun1();
}
}
A::fun2();  // returns BooMBa
  1. A::func2()-对A::func2的静态调用
  2. static::fun1()-对A::func1的静态调用,没有实例
  3. echo (new self)->a-创建A的新实例并回显刚刚创建的实例的变量a的内容

A::func2的每次调用都会在步骤3 中创建A的新实例


class A {
public $a = "BooMBa";
public function fun1() {
echo $this->a; 
}
public function fun2() {
return $this->fun1();
}
}
$a = new A();
$a->fun2();  // returns BooMBa
  1. $a = new A()-创建A的新实例
  2. $a->fun2()-调用实例$a的方法fun2
  3. $this->fun1()-调用当前实例的方法fun1($a)
  4. echo $this->a—当前实例的a的echo内容($a)

$this是指类的当前实例,但如果您调用static,则没有实例。new self创建类的新实例,允许您使用$this,因为您有引用的实例


让我们以猫为例。Cat的实例就是站在您面前的某个$cat。您可以要求您的$catpurrr,因为您引用了cat的具体实例,所以在该cat的方法purrr中,您可以引用$this并调用echo $this->purrrSound。当您进行静态调用时,您将调用Cat的抽象概念,并没有Cat的特定实例,也没有可引用的$this

class Cat {
public $purrrSound = "purrrrr...";
public function purrr() {
echo $this->purrrSound;
}
}
$cat = new Cat();
$cat->purrr(); // kittty purrrr, please?
// Cat::purrr(); // all the Cats in the universe, purrr now?  

静态上下文

在PHP中,您可以使用范围解析运算符::静态调用方法。因此,这个表达式只是一个静态调用:

return static::fun1()

当您处于静态上下文中时(在静态调用之后),$this不起作用——这是一种语言断言。即使在静态上下文中,这个表达式仍然有效:

(new self)->a

只是因为你在白痴对象的一个新实例,然后得到它的公共属性。


不推荐注释:

小心在PHP 5中,静态调用非静态方法会生成E_STRICT级别警告。

警告在PHP 7中,不赞成静态调用非静态方法,并且将生成E_ DEPRECATED警告。支持呼叫非静态方法可能在将来被静态地移除。

请考虑:

考虑不要使用静态方法,因为它是其他类的耦合,通常只是静态方法中的过程代码闭合。例如,在一个新类中实现这个函数,并在需要时使用依赖注入

最新更新