Hey guys :) # Abstract Classes Establishing a contract that any child class of an abstract class has to be immutable is a totally valid use case in my opinion and it aids consistency. Otherwise we have the same situation as with final which I never understood. Actually, even interfaces could benefit from this modifier.
# Clone What Larry illustrated is exactly how I build immutable value objects right now too. However, cloning as we have it is not what we want, we want a mutable clone while cloning is not allowed to the outside world. It simply makes no sense to clone a value object for the same reason as it makes no sense to clone a string. On a side note, I always change the visibility of the __clone callback in my value objects to protected/private and disable cloning for the outside world this way. Cloning a value object is a programming error and not something that should be catchable and recoverable. I see various ways to approach this topic and did not include anything in the previous message because I wanted to think a bit more about it. ## Proposal 1 My first proposal would be to allow mutation within the class itself but directly creating a copy to ensure integrity and immutability of the current instance. final immutable class ValueObject { public $value; public function withValue($value) { $this->value = $value; return $this; } } The write is happening in a compatible context (within the class), however, the $this variable contains a copy of the original now with the changed value instead of the actual instance. Not returning it means that it is simply lost and the state of the current instance is never touched. public function withValue($value) { if ($value !== null) { $this->value = $value; } return $this; } If $value is null the same instance is returned as is since no write happened. The only thing I do not like about this approach is that it is implicit and not explicit. At the same time it avoids all kinds of problems since the engine handles everything for you and it requires less typing. ## Proposal 2 The __clone callback returns an instance that is mutable within the class itself but not from the outside. This is pretty much like the first proposal but making the clone operation explicit. Note that any write to the current instance would always be an error here. public function withValue($value) { if ($value !== null) { $copy = clone $this; $copy->value = $value; return $copy; } return $this; } Significantly more typing and of course a source of error because the engine does not take care of the work for you. # Arrays and Resources This definitely needs clarification in the RFC since it is a very important restriction. # Flyweight Thinking about it, it's actually possible with the current implementation to create it by simply leaving of the modifier from the class. final class Flyweight { private static $instances = []; public immutable $value; } Hence, forget about the remark. # Dynamic Properties Should definitely error on write and it should be explained in the RFC. -- Richard "Fleshgrinder" Fussenegger
signature.asc
Description: OpenPGP digital signature