为什么$ this关键字给出了静态的致命错误但是(新的自我)工作正常

时间:2017-11-02 06:39:29

标签: php

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)

PS:请考虑我在下面给出了Q& A部分以及更多文章,但是无法准确了解这个特定情况下发生了什么。
Reference
What does new self(); mean in PHP?
PHP : Difference b/w new self and new object()
PHP: The Basics Manual

PPS:除了相同的错误消息之外,此Q& A in PHP, what is the difference between self and $this?与我无关。这是完全不同的背景。在那个问题中,他只是静态地调用非静态方法。与此同时,我的问题对于后期静态绑定和关键字(新自我)来说更复杂。完全不可能通过上述Q& A中的答案来理解我的问题,所以请在标记为重复之前通过Q& A。谢谢。

2 个答案:

答案 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'

}
  1. 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()
  2. A::func2 - 创建(new self)->fun1()的实例并调用该实例的A
  3. fun1 - 回显当前echo $this->a的内容(在步骤2中创建)实例
  4. 每次调用a都会在第2步中创建A::func2的新实例

    A
    1. class A { public $a = "BooMBa"; public function fun1() { echo $this->a; } public static function fun2() { return static::fun1(); } } A::fun2(); // fails - 静态调用A::func2()
    2. A::func2 - 对static::fun1()的静态调用,没有实例。 AFAIK这应该生成警告,因为您对实例方法进行静态调用
    3. A::func1 - 回显当前实例的echo $this->a;内容,但是因为我们来自静态调用所以没有实例,我们在类范围内。错误
    4. a
      1. 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()
      2. A::func2 - 静态调用static::fun1(),没有实例
      3. A::func1 - 创建echo (new self)->a的新实例并回显刚刚创建的实例的变量A的内容
      4. 每次调用a都会在第3步中创建A::func2的新实例

        A
        1. 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()
        2. 的新实例
        3. A - 实例$a->fun2()
        4. 的调用方法fun2
        5. $a - 当前实例的调用方法$this->fun1()fun1
        6. $a - 回显当前实例echo $this->a的内容(a
        7. $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警告。支持通话   静态的非静态方法将来可能会被删除。

供您考虑:

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