ChatGPT解决这个技术问题 Extra ChatGPT

New self vs. new static

I am converting a PHP 5.3 library to work on PHP 5.2. The main thing standing in my way is the use of late static binding like return new static($options); , if I convert this to return new self($options) will I get the same results?

What is the difference between new self and new static?


m
mleko

will I get the same results?

Not really. I don't know of a workaround for PHP 5.2, though.

What is the difference between new self and new static?

self refers to the same class in which the new keyword is actually written.

static, in PHP 5.3's late static bindings, refers to whatever class in the hierarchy you called the method on.

In the following example, B inherits both methods from A. The self invocation is bound to A because it's defined in A's implementation of the first method, whereas static is bound to the called class (also see get_called_class()).

class A {
    public static function get_self() {
        return new self();
    }

    public static function get_static() {
        return new static();
    }
}

class B extends A {}

echo get_class(B::get_self());  // A
echo get_class(B::get_static()); // B
echo get_class(A::get_self()); // A
echo get_class(A::get_static()); // A

makes sense. I think the best bet is to pass the class name to the function that is using late static binding and then do return new $className($options);
You don't have to "pass" the class name, you can always do get_called_class(), which is effectively the same as __CLASS__, but LSB compatible.
get_called_class does not exist in
The function called as self::theFunction() behaves like "I will execute in the context of the class whom I physically belong to." and the function called as static::theFunction() behaves like "I will execute in the context of the class which has been actually called by the outside world". ( Assuming the inheritance scenario ). Thanks
In my head, I just take whatever is intuitive, and make it opposite. You would think based on the naming, self would return itself, and static would return something that cannot be overridden... But lo and behold it's the opposite. I never cease to be impressed by PHP's naming, conventions, and overall style. -_-
s
stefanos gian

If the method of this code is not static, you can get a work-around in 5.2 by using get_class($this).

class A {
    public function create1() {
        $class = get_class($this);
        return new $class();
    }
    public function create2() {
        return new static();
    }
}

class B extends A {

}

$b = new B();
var_dump(get_class($b->create1()), get_class($b->create2()));

The results:

string(1) "B"
string(1) "B"

If the method isn't static then late static bindings become totally irrelevant.
For example, you could use it in "copy" method, where object is copied without using clone, but just by re-creating and setting the properties. $copy = new static(); $copy->set($this->get()); return $copy;
@BoltClock Surely not? If you're calling an overridden static method from within an instance method of a subclass, then your choice of self:: or static:: is going to affect whether the base class's or subclass's version of that static method is used. In the absence of some reason to think that such a situation occurring inherently indicates bad practice (and I don't see any reason why this should be so), the choice between self:: and static:: is just as relevant within non-static methods as it is in static methods. Have I misunderstood your comment, or is one us simply wrong?
@Mark Amery: Hmm I didn't think of that. You're absolutely right. I had assumed that no static methods were going to be called in the instance method in question, but based on your example, I can see how that would be a very naïve assumption.
R
Rain

In addition to others' answers :

static:: will be computed using runtime information.

That means you can't use static:: in a class property because properties values :

Must be able to be evaluated at compile time and must not depend on run-time information.

class Foo {
    public $name = static::class;

}

$Foo = new Foo;
echo $Foo->name; // Fatal error

Using self::

class Foo {
    public $name = self::class;

}
$Foo = new Foo;
echo $Foo->name; // Foo

Please note that the Fatal error comment in the code i made doesn't indicate where the error happened, the error happened earlier before the object was instantiated as @Grapestain mentioned in the comments


Note the error is thrown on line 2 public $name = static::class;, not on line 7, as suggested by the example. The error says: "static::class cannot be used for compile-time class name resolution" which indicates the problem is not where you try to access the $name field, but far before, at the compilation of the PHP class. Line 7 (or 6) will not be reached in the first example.
Right, I did not mean to criticise, just clarified what confused me first in the hope it may help others. Helpful example anyway!