When my class returns a modified new instance of the class itself instead of modifying it itself, is it a project pattern?

Asked

Viewed 369 times

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 given method makes to the items contained in this collection.

Usually, when I see class development in PHP, it is not very common to do this, because it usually returns itself $this to refer to classe current.

To illustrate my doubt, I will 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;
    }


}

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

But I’ve seen it in class Illuminate Support Collection, from Laravel, some methods 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, it is used new static instead of $this.

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

About that difference, I’d like to know:

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

  • Use that new static would not be a problem of structure, since if I inherit this class, I can change the builder, and new static would be harmed, having to be changed in all methods?

Updating

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

  class KeyValueCollection extends Collection

  {
         public function __construct(array $keys, array $values)
         {
              parent::construct(array_combine($keys, $values));
         }
  }

When I call the method KeyValueCollection::filter inherited by Collection, an error will be generated as new static is now referencing the KeyValueCollection, who need to two parameters in the builder, and not a.

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

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

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

  • 1

    The standard 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.

  • @Brunorb I know that the Laravel is a well-known framework, but it would not be wrong to use new static, since if you change the constructor, all calls would have to be changed as well? Wouldn’t it be better to use the clone $this for such an operation?

  • 1

    I don’t understand the question.

  • @Mustache I’m having a little trouble expressing that doubt. But what I mean first is that it is a pattern "not to change the class itself, but to bring in a new instance with the modifications "... And then, if this would not be an encoding problem, since if I extend this class that always creates a new instance, with a constructor with different parameters, the other calls of new Static would be impaired

  • This last part I’m not understanding, I don’t know what problem is this that you’re seeing.

  • I’m going to edit the question and ask the question you’re asking me

  • 1

    Excuse me all. I thought that in PHP it was not possible to define a behavior for the constructor through an interface, but it is possible yes. That solved my problem :D

Show 2 more comments

1 answer

3


  1. The pattern is immutability, transformations into 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.
  2. Extending a class and changing the signature of a superscript method, the constructor in this case, is considered bad practice and violates the the principle of Liskov’s replacement, you break the possibility of programming to an interface since it is not guaranteed that it and its implementations have the same signatures, so I would say the use of new static is not a design mistake.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.