rfc:propertygetsetsyntax-alternative-typehinting-syntax

This is an old revision of the document!


Request for Comments: Alternative typehinting syntax for accessors

  • Date: 2013-01-04
  • Author: Nikita Popov nikic@php.net
  • Status: Under Discussion

Introduction

This RFC proposes a different typehinting syntax for the property accessors proposal. The proposed syntax places the typehint before the property name rather than in the set accessor's parameter declaration. This optimizes a common use of accessor properties and aligns the syntax with other languages. In particular it will allow to typehint properties without specifying accessors (public DateTime $date;).

Current syntax(es)

The current accessors RFC implements two syntax variations for accessors. The first is the original parentheses-less form using the magic $values variable:

private $seconds;
public $hours {
    get { return $this->seconds / 3600; }
    set { $this->seconds = $value * 3600; }
}

The newly added second syntax allows specifying the accessors in a more function-like form:

private $seconds;
public $hours {
    get() { return $this->seconds / 3600; }
    set($hours) { $this->seconds = $hours * 3600; }
}

One of the reasons to add the latter syntax is to allow typehinting the setter. E.g. this allows to do something like the following:

public $date {
    get() { return $this->date; }
    set(DateTime $date) { $this->date = $date; }
}

The $date property implemented above behaves the same way as a normal property, but only allows to be assigned DateTime instances. Using automatic accessors it is possible to implement the same with a bit less boilerplate:

public $date {
    get;
    set(DateTime $date);
}

Typehinting

There is clear evidence that typehinting is of great importance to PHP developers. This doesn't only apply to ordinary methods, but also to accessors. An analysis of the Symfony 2.1 Standard Distribution 1) has shown that about a third of all setXYZ()-style methods are typehinted. About 15% of the setters are actually only typehinting and don't perform any other action than enforcing the typehint.

Thus the main objective of this proposal is to improve the typehinting aspect of the accessors proposal.

Proposed syntax

This RFC proposes to change the current syntax for typehinted accessors...

public $date {
    get() { return $this->date; }
    set(DateTime $date) { $this->date = $date; }
}

... by moving the typehint in front of the property name:

public DateTime $date {
    get { return $this->date; }
    set { $this->date = $value; }
}

Automatic accessors can be used to reduce the boilerplate:

public DateTime $date { get; set; }

Which again is equivalent to just the property with the typehint:

public DateTime $date;

Benefits of the proposed syntax

The proposed syntax has several benefits over the current syntax, with the main one being that it optimizes a very common use case (while not making other use cases worse). As mentioned above about 15% of all accessor methods in Symfony would be able to use the public DateTime $date style shorthand notation.

Even when the shorthand can not be used (because one actually defines some accessors) I would argue that the proposed syntax is more elegant than the current one, mainly because the relevant API information is focused at one point at the start of the declaration. For interacting with the class only the visibility and the typehint are of importance, whereas the actual implementation is irrelevant. The public DateTime $date { ... } syntax does a better job at conveying the relevant bits than the current syntax:

public $date { // <-- This is important
    get {
        // Some
        // Rather
        // Long
        // Code
    }
    set(DateTime $date) { // <-- And the typehint here is important, too
        // Some
        // Further
        // Code
        // Here
    }
}

Another benefit I see in this typehint syntax is that most programmers are already familiar with it, because virtually every strongly typed language uses it. Most dynamic languages with support for optional typing that I know (like Dart or TypeScript) also use this syntax. This makes the syntax a lot more intuitive. If you want to typehint a property your first try will probably be putting the typename in front of it, rather than coming up with something like public $date { get; set(DateTime $date); }. I think the latter syntax isn't particularly hard to understand *once you know it*, but it's not something that comes up intuitively.

One last benefit that comes from this syntax is that we no longer need two ways to specify accessors (with and without parentheses). Though I also heard the opinion from some people that both syntaxes should be still kept to avoid the $value magic variable. I'd probably be okay either way, but I personally dislike it if there are two very similar ways to do one thing.

Common Misconceptions

When I brought this up last time the discussion showed some misconceptions regarding this proposal. This seems to be inherent to any discussion involving typehints in some way, so I decided to clear some things up beforehand.

The important thing to realize is that this proposal does not add new typehinting concepts to PHP. It's just suggests a more general, more convenient and more familiar syntax for what already exists in the accessors proposal. The public DateTime $date; syntax is exactly equivalent to the following snippet using the current syntax:

public $date {
    get;
    set(DateTime $date);
}

The last time I brought this up most of the discussion focused on the question whether typehints in PHP are a good idea in general and I would like to prevent this kind of discussion this time, as it is only tangentially related. Fact is that we do have typehints for methods and that those typehints are used a lot. Fact is that the typehints are also used a lot on accessors (30%) and often *just* for the typehint (15%). Fact also is that the accessors proposal makes the normal method typehints apply to properties. So the question really isn't whether typehints on properties are a good idea, the question is rather whether we want to have the convoluted public $date { get; set(DateTime $date); } syntax all over the code or the familiar and clearer public DateTime $date; syntax.

I understand that some people on internals disapprove of typehints in general and that they have reasons to do so. I hope that those people will be able to consider this without prejudice and on its actual merits concerning the actual use of the language. Thanks.

Patch

I haven't written a patch for this yet, but the change from the current syntax to this one is rather simple. The current accessors proposal will need special handling of the typehint in any case (it can't be handled as a normal method typehint). The proposed syntax would actually make the handling slightly simpler.

1)
The Symfony Standard Distribution is a collection of several large object-oriented projects written in PHP, as such I think it is a good representative to collect this kind of statistics
rfc/propertygetsetsyntax-alternative-typehinting-syntax.1357309018.txt.gz · Last modified: 2017/09/22 13:28 (external edit)