On Wed, Mar 16, 2016 at 12:50 PM, Larry Garfield <la...@garfieldtech.com>
wrote:

> On 3/16/16 11:36 AM, Phil Sturgeon wrote:
>
>>
>> 2. This whole temporary nullability situation, where unset properties
>> will error on attempted usage if not set. Should they instead error
>> after the constructor has been called if they are still not holding a
>> value?
>>
>
> I fall back to a statement I made in a blog post a while back:
>
> http://www.garfieldtech.com/blog/empty-return-values
>
> " But consider what you could do instead that would not force me to throw
> is_null() around my code, because throwing is_null() around my code makes
> me sad. NULL should be the return value of last resort, because it means
> nothing. (Literally.)"
>
> Allowing default-null on properties means that as someone using that
> property, I have two options:
>
> 1) Throw a lot of is_null() calls around my code.
> 2) Assume that whoever initialized the code provided a value by the time
> initialization is done and skip those extra checks.
>
> Insert that old adage about what happens when you assume.
>
> End-of-constructor checks seem like a good approach; they have to be
> uninitialized at some point when new is called initially, but they should
> be guaranteed set as soon as possible.  End of the constructor is "as soon
> as possible", and I think reasonably static-analysis-catchable.  (Meaning
> my IDE can yell at me appropriately.)
>
> That removes is_null() calls from the rest of my codebase, which is a good
> thing.
>
>
I'm not sure I like the "after contructor" because that's not necessarily
when the object is finished being initialized. Consider this:

abstract class Contract
{
    private function __construct() {}

    public static function fromArray(array $aProps) : Contract
    {
        $s = new static();
        foreach ($aProps as $k => $v) {
            if (property_exists(static::class, $k)) {
                $s->$k = $v;
            }
        }

        return $s;
    }
}

class User extends Contract {
   public int $id;
   public string $name;
}

$user = User::fromArray(['id' => 123, 'name' => 'derokorian']);

In this example, the constructor finishes but the properties still are not
initialized at time of finishing. This is a pretty common pattern as well.

Reply via email to