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)
。
PPS:除了相同的错误消息之外,此Q& A in PHP, what is the difference between self and $this?与我无关。这是完全不同的背景。在那个问题中,他只是静态地调用非静态方法。与此同时,我的问题对于后期静态绑定和关键字(新自我)来说更复杂。完全不可能通过上述Q& A中的答案来理解我的问题,所以请在标记为重复之前通过Q& A。谢谢。
答案 0 :(得分:1)
这个问题来自“阶级和实例之间的区别”。
我将简化您的示例并逐步进行。
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile('com.mikepenz:aboutlibraries:5.9.7@aar') {
transitive = true
exclude group: 'com.android.support'
}
compile 'com.android.support:appcompat-v7:26.0.1'
compile 'com.android.support:multidex:1.0.1'
compile 'com.android.support:design:26.0.1'
compile 'com.android.support:recyclerview-v7:26.0.1'
compile 'com.android.support:cardview-v7:26.0.+'
compile 'com.google.android.gms:play-services-auth:9.2.1'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
compile 'com.android.volley:volley:1.0.0'
compile 'com.github.lolucosmin:PermissionsWrapper:version_1.2'
compile 'com.github.javiersantos:BottomDialogs:1.2.1'
compile 'com.toptoche.searchablespinner:searchablespinnerlibrary:1.3.1'
compile 'com.appyvet:materialrangebar:1.4'
compile 'com.github.vivchar:ViewPagerIndicator:v1.0.1'
compile 'com.github.bumptech.glide:glide:4.2.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.2.0'
compile 'com.github.chathuralakmal:AndroidImagePopup:1.2'
compile 'com.ss.bannerslider:bannerslider:1.8.0'
compile 'org.aviran.cookiebar2:cookiebar2:1.0.5'
compile 'com.github.hamsaadev:RTLMaterialSpinner:V1.0.1'
compile 'com.github.darsh2:MultipleImageSelect:v0.0.4'
}
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
都会在第2步中创建A::func2
的新实例
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()
的静态调用,没有实例。 AFAIK这应该生成警告,因为您对实例方法进行静态调用A::func1
- 回显当前实例的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
都会在第3步中创建A::func2
的新实例
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()
fun2
$a
- 当前实例的调用方法$this->fun1()
(fun1
)$a
- 回显当前实例echo $this->a
的内容(a
) $a
指的是当前的类实例,但是如果你$this
调用,则没有实例。
static
创建了一个新的类实例,允许您使用new self
,因为您有实例可以引用
让我们以猫为例。 $this
的实例是站在您面前的一些Cat
。您可以询问$cat
$cat
,因为您引用猫的具体实例,在该猫的方法purrr
内,您可以参考purrr
并致电{{1 }}。
当您进行静态调用时,您调用$this
的抽象概念,没有echo $this->purrrSound
的特定实例,并且没有Cat
可以引用。
Cat
答案 1 :(得分:0)
在PHP中,您可以使用“范围分辨率运算符”运算符::
静态调用方法。所以,这个表达式只是一个静态调用:
return static::fun1()
当你处于静态上下文(静态调用之后)$this
不起作用时 - 它是一种语言断言。即使在静态上下文中,该表达式仍然有效:
(new self)->a
只是因为你正在创建一个新的对象实例,然后获得它的公共财产。
注意在PHP 5中,静态调用非静态方法会生成一个 E_STRICT级别警告。
警告在PHP 7中,不推荐静态调用非静态方法, 并将生成E_DEPRECATED警告。支持通话 静态的非静态方法将来可能会被删除。
供您考虑:
考虑不要使用静态方法,因为它是其他类的耦合,并且它通常只是在静态方法中关闭的过程代码。例如,在新类中实现此函数,并在需要时使用依赖注入。