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
A::func2()
-对A::func2
的静态调用(new self)->fun1()
-创建A
的实例并调用该实例的fun1
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
A::func2()
-对A::func2
的静态调用static::fun1()
-对A::func1
的静态调用,没有实例。AFAIK这应该会生成警告,因为您对实例方法进行了静态调用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
A::func2()
-对A::func2
的静态调用static::fun1()
-对A::func1
的静态调用,没有实例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
$a = new A()
-创建A
的新实例$a->fun2()
-调用实例$a
的方法fun2
$this->fun1()
-调用当前实例的方法fun1
($a
)echo $this->a
—当前实例的a
的echo内容($a
)
$this
是指类的当前实例,但如果您调用static
,则没有实例。new self
创建类的新实例,允许您使用$this
,因为您有引用的实例
让我们以猫为例。Cat
的实例就是站在您面前的某个$cat
。您可以要求您的$cat
到purrr
,因为您引用了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警告。支持呼叫非静态方法可能在将来被静态地移除。
请考虑:
考虑不要使用静态方法,因为它是其他类的耦合,通常只是静态方法中的过程代码闭合。例如,在一个新类中实现这个函数,并在需要时使用依赖注入