$this in php is bound dynamically, right?

2019-09-02 06:01发布

问题:

I'm getting an error that I think is because I've made some kind of mistake in a refactoring, but I can't find documentation on when $this is bound, and my error could be explained by it being bound statically.

Extra points (I can't actually give you extra points) for links to excellent documentation about this kind of thing in php.

[Edit] The error that I'm getting is telling me that Subclass::$var doesn't exist when I do, for example, echo $this->var in a superclass. The $var exists in the subclass, though.

回答1:

This works in PHP:

class A {
    public function foo() {
        echo $this->bar;
    }
}

class B extends A {
    public $bar = 1;
}

$b = new B;
$b->foo();  // 1

It works because of the dynamic scope resolution that PHP has (i.e.: scope is resolved at runtime as opposed to compile time). However, I'd recommend against it, because it is really a particularity of the language for one. For second, failing to declare $bar in a subclass would result in an error. I think that a class should only reference members that it is aware of.

The same code, say in C++:

class A {

public:
    void foo() {
        std::cout << bar;
    }

};

class B : public A {

public:
    int bar;
    B() {
        bar = 1;
    }

};

...would give you a compile error (In A::foo(): 'bar' was not declared in this scope).



回答2:

$this becomes available after you've called the constructor. Logically you can't use $this in a static function.

Aside from calling $this in a static function there isn't a whole lot that can go wrong timing wise as there is simply no way in PHP.

What exactly is the error you're getting? Code would useful too.



回答3:

Yes, $this is bound dynamically, as is evidenced by the fact that the output of the following is "foo":

<?php
class Base
{
    public function ecc(){
        echo $this->subvar;
    }
}

class Sub extends Base
{
    public $subvar;
    public function __construct(){
        $this->subvar = 'foo';
        $this->ecc();
    }
}
new Sub();
?>