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, andnew 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?
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
Laravel
is 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 $this
for 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