On 05/04/2024 01:20, Saki Takamachi wrote:
I don't think it will be possible to make a good Money class as a child of 
this. BcNum is a read-only class, so if the constructor of BcNum is final then 
the child class won't be able to take the currency as a constructor param, and 
won't be able to protect the invariant that currency must be initialized. If 
the constructor of BcNum were made non-final then BcNum wouldn't be able to 
protect the invariant of the numeric value always being initialized once the 
constructor has returned. And it should be straightforward to make a good money 
class as a composition of BcNum and a currency enum or string.
The RFC does not list the constructor as final, and I would not expect it to.
There's probably not any good use case for a subclass to add properties, unless 
perhaps the subclass developers are willing do do away with some of the checks 
that would normally be done on a value object by the PHP runtime to keep it 
valid (maybe replacing them with static analysis checks). But there are lots of 
reasonable use cases for subclasses to add methods, even if they're effectively 
syntax sugar for static methods with a BcNum typed param.
I literally just provided in the quote you are replying to a good use case for 
a subclass. You can do the same thing with composition yeah, and that might 
even be better to a lot of people, but I don't think this RFC should take a 
position AGAINST subclasses and in favor of composition.
Having just written that I've now checked the behavior of DateTime - 
seehttps://3v4l.org/5DQZg. The constructor of that isn't final, so a child 
class can replace it with an empty constructor. But if it does that and leaves 
the value uninitialized then it blows up on a call to `format`. That's probably 
not something we should emulate. DateTimeImmutable behaves the same way.
Why not? Writing something like that obviously does not work, and the error 
would be immediately apparent. Is it possible to create something that will 
error? Of course. That's not an error that needs to be aggressively guarded 
against, because the feedback is rapid and obvious.

I don't think protecting initialization by the constructor is 
necessary.https://3v4l.org/YroTN
This problem can occur with any class, not just `DateTime`. And I think this is 
the responsibility of the user's code, and the language just needs to throw an 
exception appropriately.

To clarify: In my opinion, I think that value objects provided by languages 
​​are not intended to force immutability or design onto users, to provide 
functionality to users who expect them to behave as immutable value objects. 
Therefore, even if a child class that inherits from `Number` behaves in a way 
that is not immutable, it is the responsibility of the user and there is no 
need to prohibit it.

In other words, the concerns we are currently aware of are issues of 
responsibility on the user's side, and my opinion is that there is no need to 
give that much consideration. However, this is my personal opinion, and there 
may be more reasonable opinions.


Ah ok. Maybe that's the standard way internal classes are written, and we can consider it generally an error for a child class to override the constructor without calling `parent::__construct()`. I know tools warn users not to forget the parent call.

And I had been thinking of BcNum as a readonly class, but I see it's not an readonly class, it's a mutable class with its one and only property being readonly.  I agree that it seems unnecessary to force child classes to be immutable - I wasn't concerned about them adding additional, mutable, properties, only about leaving the value property uninitialized. (Btw I would have supported the 1st part of the 2022 Readonly amendments RFC, which I think would have made a readonly class behave the same as a class where every property is readonly, particularly since would have allowed implementing the example given on the Wikipedia page for LSP: a circle with fixed centre and mutable radius may inherit from an immutable point)

Reply via email to