On Mon, 16 Sep 2019 at 08:29, Michał Brzuchalski <
michal.brzuchal...@gmail.com> wrote:

> Please keep in mind that initializing properties through object initializer
> applies to visible properties and is possible to assign
> protected or private properties from the class scope as well.
>


The problem with that is that you need an extra static method to make use
of it, and you still need to get the arguments into that method. It might
be useful occasionally, but it still doesn't help constructors which are
setting a large number of private / protected properties.



> I don't see the reasons why many of you consider public properties a bad
> solution. PHP language has support for public properties
> and with typed properties, it is possible to ensure valid object state
> using VO's which are valid all the time, consider Uuid userland
> implementation
> no one checks if that's valid UUID, cause it's ensured by VO.
>


Firstly, it's not necessarily a case of "considering public properties a
bad solution"; it's about evaluating where the new feature could be used,
and where it wouldn't help. If there was a feature which helped this use
case *and* other use cases, I think that would be "better", but that
doesn't make this feature "bad".

Secondly, typed properties certainly make public properties more appealing,
but there are still a bunch of things that you can't do with them, like
declaring them readonly, or having logic other than type validation in
getters and setters. Note that C#, which has object initializers, also has
these features, making them a lot more powerful.




> Any kind of features like promoting arguments from the constructor or named
> arguments are fine but not efficient in those cases.
> Any good practices suggest limiting function|method arguments while the
> case is where there is a significant amount of properties
> to be initialized and additionally which don't need any kind of validation
> due to VO, or simple scalars.
>



That's a good point; named parameters make function calls scale much better
to long lists of parameters, but *declaring* the constructor would still be
unwieldy. The only way to improve that would be for the class to
effectively opt into having an initializer using a special syntax for the
constructor. Larry gave this example syntax:

class Employee {
  protected int $age;
  protected string $name;
  protected ?Employee $boss;

  public function hoist __construct() {
    if ($age < 18) throw new ChildLaborException();
  }
}

And Paul M Jones mentioned this version from Hack, where the parameters are
listed in the constructor, but don't need to be re-listed outside it:

class Employee {
 public function __construct(
    protected int $age,
    protected string $name,
    protected ?Employee $boss
  ) {
    if ($age < 18) throw new ChildLaborException();
  }
}


Either of those, with named parameters, would be almost indistinguishable
from object initializers at the call site. Depending on the syntax chosen,
it might be as similar as:

// Call initializer, requires public properties
new Employee { age => 42, name => 'John Smith' };
// Call constructor, requires special constructor definition
new Employee( age => 42, name => 'John Smith' );


That would require multiple new features, though, so initializers might be
more achievable in the short term, and perhaps there is room for both,
particularly if support for getters and setters improves.


Regards,
-- 
Rowan Tommins
[IMSoP]

Reply via email to