Returning of new $this with abstract classes

I found some trouble with my code and do not understand why it's doing as it is. Can anyone explain me?

Let we have:

abstract class AbstractThing
{
    public function search(...)
    {
        $ret = false;

        $data = $database->query(...);
        foreach($data as $values)
        {
            $item  = new $this;
            $item->fill_with_values($values);

            $ret []= $item;
        }

        return $ret;
    }
}

It's works as intended and return object instances at success searches:

class Thing extends AbstractThing
{
    // ...
}

$thing = new Thing;
$things = $thing->search(...); // Thing[] on success, false on failure

But if I wish to shorten code very slightly, it breaks:

abstract class AbstractThing
{
    public function search(...)
    {
        $ret = false;

        $data = $database->query(...);
        foreach($data as $values) {
            $ret []= (new $this)->fill_with_values($values);
        }

        return $ret;
    }
}

This return boolean true. Why? It works well on the classes that are not inherited from abstract class.


When we assign:

$ret []= (new $this)->fill_with_values($values);

...we're not setting $ret[] = (new $this) . Instead, this statement pushes the return value of fill_with_values() into the array because it executes last.

It looks like you're trying to implement something similar to the factory method pattern. Consider this:

abstract class AbstractThing
{ 
    ...
    public static function fill($values) 
    { 
        $instance = new static; 
        $instance->fill_with_values($values);

        return $instance; 
    }
}

Then we can actually do what you're trying to accomplish in your question like this:

$ret[] = static::fill($values);

This works because the return value of fill() is the instance of the class, not the return value of fill_with_values() . The static keyword in this context uses late static binding to resolve the type of the class that executes the code ( Thing in this case) instead of the class that declares it, so it works through inheritance. See this question for more information.


The code does 2 different things:

This adds $item to your "$ret" array:

        $item  = new $this;
        $item->fill_with_values($values);

        $ret []= $item;

This adds the returned value of "fill_with_values" to your array:

$ret []= (new $this)->fill_with_values($values);

The equivalent of the above code would be:

        $item  = new $this;
        $return = $item->fill_with_values($values);
        $ret []= $return;

If I knew what was going on in your "fill_with_values" method I could tell you why it is a boolean, but the code does not do the same thing. Hope that makes sense.


Ok, finally it was my own error. There was really possibility to return TRUE from fill_with_values() function at some point. Sorry all for bad questions and thanks for answers!

链接地址: http://www.djcxy.com/p/58038.html

上一篇: 如何静态调用方法?

下一篇: 用抽象类返回新$