Why return new static? (PHP)

2019-03-09 20:12发布

问题:

Why some people create one method that returns new static instead of making all of the methods static? What is the reason to have that method that returns new static? I am not asking what is the difference between static and self, or what static & self mean. For example, here is one simple class:

<?php

class Expression
{
    public static function make()
    {
        return new static;
    }


    public function find($value)
    {
        return '/' . $value .'/';
    }

    public function then($value)  
    {
        return $this->find($value);
    }

    public function hi($value)  
    {
        return "hi";
    }

}

As you can see, there is a static method make() which returns new static. Then, some people call other methods like this:

$regex = Expression::make()->find('www');

What is the purpose of it? I see that here we don't use new Expression syntax, and if that's the point - then why they didn't make all methods to be, for example, static? What is the difference, what is the reason to have that method which returns new static?

回答1:

new static instantiates a new object from the current class, and works with late static bindings (instantiates the subclass if the class was subclassed, I expect you understand that).

Having a static method on a class which returns a new instance of same is an alternative constructor. Meaning, typically your constructor is public function __construct, and typically it requires a certain bunch of parameters:

class Foo {
    public function __construct(BarInterface $bar, array $baz = []) { ... }
}

Having an alternative constructor allows you to provide different defaults, or convenience shortcuts to instantiate this class without having to supply those specific arguments and/or for being able to provide different arguments which the alternative constructor will convert to the canonical ones:

class Foo {

    public function __construct(BarInterface $bar, array $baz = []) { ... }

    public static function fromBarString($bar) {
        return new static(new Bar($bar));
    }

    public static function getDefault() {
        return new static(new Bar('baz'), [42]);
    }

}

Now, even though your canonical constructor requires a bunch of complex arguments, you can create a default instance of your class, which will probably be fine for most uses, simply with Foo::getDefault().

The canonical example in PHP for this is DateTime and DateTime::createFromFormat.

In your concrete example the alternative constructor doesn't actually do anything, so it's rather superfluous, but I expect that's because it's an incomplete example. If there's indeed an alternative constructor which does nothing other than new static, it's probably just meant as convenience syntax over (new Foo)->, which I find questionable.



回答2:

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