When my class returns a new modified instance of the class itself instead of modifying itself is this some design pattern?

3

I'm developing a class that is a collection of values. In it I have several methods that filter the values contained in this collection. My intention is to return a new instance of this same class depending on the modification that a given method makes to the items contained in that collection.

Generally, when I see classes development in PHP, it is not very common to do this, since the $this is usually returned to refer to classe current.

To illustrate my doubt, I'll demonstrate a collection as an example:

class Collection
{
    protected $items = [];

    public function __construct(array $items = [])
    {
        $this->items = $items;
    }

    public function filter(\Closure $callback)
    {
        $this->items = array_filter($this->items, $callback);

        return $this;
    }

    public function map(\Closure $callback)
    {
        $this->items = array_map($callback, $this->items, array_keys($this->items));

        return $this;
    }


}

Notice that with each method, the values of $items are changed and the instance itself is returned.

But I've seen Laravel's Illuminate \ Support \ Collection class, some method in the Collection classes that do something a little different: Instead of returning the instance itself, a new instance is returned for the modified values.

class Collection

{
    protected $items = [];

    public function __construct(array $items = [])
    {
        $this->items = $items;
    }

    public function filter(\Closure $callback)
    {
        return new static(array_filter($this->items, $callback));
    }

    public function map(\Closure $callback)
    {

        $items = array_map($callback, $this->items, array_keys($this->items));

        return new static($items);
    }

}

Note that in the second example, new static is used instead of $this .

I understand very well that this operation causes the values to be passed on in a new way, but without changing the original reference. Some cases this is very helpful.

About this difference, I would like to know:

  • Is there a name for this particular pattern / behavior in the class of the second example?

  • Using this new static would not be a structural problem, since if I inherit this class, can I change the constructor, and new static would be impaired, having to be changed in all methods? >

Update

To illustrate the second question, let me give you an example. Suppose I wanted to inherit the Collection class to create new features for it. In this new class I want to add two new parameters to construtor .

  class KeyValueCollection extends Collection

  {
         public function __construct(array $keys, array $values)
         {
              parent::construct(array_combine($keys, $values));
         }
  }
When I call the KeyValueCollection::filter method inherited by Collection , an error will be generated, as new static is now referring to KeyValueCollection , which require two parameters in the constructor, not one.

  KeyValueCollection::__construct(array $keys, array $values);

If you use new static is not to modify the class itself, how could you work around this problem, since in the first case, Collection::__construct needs a parameter.

If you need such an operation, would I have to modify all methods of the inherited class?

    
asked by anonymous 31.03.2016 / 19:37

1 answer

3
  • The default is immutability, transformations in objects and structures never change the original reference, instead they are applied to a new object / structure that is returned. This comes from functional programming and the goal is to avoid side effects.
  • Extending a class and changing the signature of an overwritten method, the constructor in this case, is considered a bad practice and violates the #, you break the possibility of programming for an interface since it is not guaranteed that it and its implementations have the same signatures, so I would say that the. use of new static is not a design error.
  • 31.03.2016 / 20:23