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 staticwould not be a problem of structure, since if I inherit this class, I can change the builder, andnew staticwould 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?
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
@Brunorb I know that the
Laravelis a well-known framework, but it would not be wrong to usenew static, since if you change the constructor, all calls would have to be changed as well? Wouldn’t it be better to use theclone $thisfor such an operation?– Wallace Maxters
I don’t understand the question.
– Maniero
@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
– Wallace Maxters
This last part I’m not understanding, I don’t know what problem is this that you’re seeing.
– Maniero
I’m going to edit the question and ask the question you’re asking me
– Wallace Maxters
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
– Wallace Maxters