On Sun, Oct 14, 2012 at 10:55 PM, Jazzer Dane <tbprogram...@gmail.com> wrote:
> One of the reasons the current syntax, as seen below, was chosen, is for
> typehints - yes.
>
>> public $property {
>>   get() { ... }
>>   set{TypeHint $value) { ... }
>> }
>>
> The other reason it was chosen was to specifically get rid of the magic
> $value that appeared out of thin air. If typehints become possible without
> having to specify it in the set accessor, I'd still argue that the syntax
> needs to stay as, in my opinion, it is the most cohesive and sensible
> syntax that was proposed - even compared to:
>
>> public $property {
>>   get { ... }
>>   set { ... }
>> }
>>
>
>
> In terms of interfaces, Clint's reason for allowing accessors in interfaces
> is moderately sensible: to remain cohesive with the already allowed __get
> and __set magic methods that are usable in interfaces.* That's the
> underlying issue.* If we want to require an object to be able to be
> converted to a string, we can sensibly put __toString in the interface. But
> what does forcefully implementing __get or __set do for the object? What
> does it tell us about how we're able to use it? It relates to properties in
> arguably such a manner that we(i.e. accessing the object's API) nor the
> interface should care about. But that's an argument for another day.

I don't get this argument, __get and __set are allowed in interfaces
simply because they are simple methods.
And preventing them from being defined in interfaces would be an extra
step that brings nothing. In fact nothing prevents you from using them
as methods.

Here we are talking about defining a specific property in terms of
their underlying accessors, which are linked to methods simply by
implementation detail. In terms of interface, it defines a specific
property, nothing more, nothing less. I see no reason to allow that
and disallow specifying "normal"properties.

>
> So what do we do right now, then? If we allow it in interfaces, my main
> worry is that people will put the accessor in an interface just because
> they can't put a property, and they'd use the accessor as a normal, basic
> property.
>
>
> And finally, in terms of protected backing properties: It seems nice, but,
> and I'm sure Clint will clarify on this, I'm not so sure that's really what
> accessors are supposed to be used for. If people want a typehinted
> property, then we should allow them to create a typehinted property rather
> than forcing them to use accessors.
>
> On Sun, Oct 14, 2012 at 5:50 AM, Nikita Popov <nikita....@gmail.com> wrote:
>
>> On Fri, Oct 12, 2012 at 7:23 AM, Clint Priest <cpri...@zerocue.com> wrote:
>> > Alright, here is the updated RFC as per discussions for the last few
>> days:
>> >
>> > https://wiki.php.net/rfc/propertygetsetsyntax-as-implemented
>> >
>> > If you could read it over, make sure I have all of your concerns
>> correctly addressed and we can leave this open for the two week waiting
>> period while I make the final code changes.
>> >
>> > -Clint
>>
>> So here comes my round of feedback on the current proposal.
>>
>> But before getting to that: I have collected a bit of data how getter
>> and setter are currently used in Symfony and ZF:
>> https://gist.github.com/3884203 Mainly so I get a better overview of
>> the situation, but might be of interest for other people involved in
>> this discussion too.
>>
>> So, my points on the proposal, in no particular order:
>>
>> 1. Typehints
>> -----------------
>>
>> The last revision of the proposal added the ability to typehint the
>> set() accessor, so that's a good start. Still I would like to go a bit
>> further on this point. My data says that about 20-30% of all setters
>> are typehinted and it is highly probable that if we had scalar
>> typehints (as I'm sure we will have in the future) that number would
>> be even larger. In particular I would like to have an easy way to
>> typehint if I *don't* want to override any additional behavior.
>> Currently that would require me to write something along the lines of
>> this:
>>
>>     protected $_date;
>>     public $date {
>>         get() { return $this->_date; }
>>         set(DateTime $date) { $this->_date = $date; }
>>     }
>>
>> This is a rather lot of boilerplate code just to add a typehint. With
>> automatic properties this might be reduced to this:
>>
>>     public $date {
>>         get();
>>         set(DateTime $date);
>>     }
>>
>> This is already a lot nicer, because I don't have to implement the
>> same getting and setting pattern again and again, but I still find
>> that it doesn't do a particularly good job at conveying its intention.
>> Rather, what that code *really* wants to say is just this:
>>
>>     public DateTime $date;
>>
>> I think that it would be very beneficial to support this syntax,
>> because I think that a large part of the use of the accessor proposal
>> will just be type checking. But if we indeed want to syntax we should
>> reconsider the get {} set { $value; } syntax again, because as I
>> understand it the new get() {} set($value) {} syntax was mainly
>> introduced to deal with setter typehints. If we chose to allow
>> typehints before the property name, then that wouldn't be necessary
>> anymore.
>>
>> 2. Interfaces
>> ------------------
>>
>> I already mentioned this before, but I'll reiterate it here again:
>> Currently properties and properties with accessors are handled
>> different with regards to interfaces. In particular, if you have an
>> interface such as follows:
>>
>>     interface Extension {
>>         public $name { get; }
>>         // more stuff
>>     }
>>
>> then the following is not a valid implementation of the interface:
>>
>>     class FooExtension implements Extension {
>>         public $name = 'foo';
>>         // more stuff
>>     }
>>
>> This does not make sense to me: $foo->name is a gettable property, as
>> such it satisfies the interface. I don't see a reason why we would
>> need a hard distinction between properties and properties with
>> accessors here.
>>
>> The converse is also true: An interface currently can not define a
>> "plain" property:
>>
>>     interface Foo {
>>         public $foo;
>>     }
>>
>> I would expect this interface definition to be the same as "public
>> $foo { get; set; }". But I'm not sure on this point, as one could
>> argue that it's just a redundant way to say the same thing.
>>
>> 3. Protected backing property
>> ------------------------------------------
>>
>> The RFC currently contains just a single code example, namely setting
>> a $Seconds property through an $Hours property, which is an example
>> where you want to override both accessors and there is a backing
>> property that already exists "naturally".
>>
>> If you on the other hand you consider cases where you only want to
>> override either the set or the get behavior and there doesn't already
>> exist a backing property, you will end up with a code like this:
>>
>>     protected $_isEnabled;
>>     public $isEnabled {
>>         get() { return $this->_isEnabled; }
>>         set($isEnabled) { $this->_isEnabled = (bool) $isEnabled; }
>>     }
>>
>> The above code really only adds a bool cast, but still it has to do
>> two things: Add a protected backing property and define a getter which
>> basically matches the default behavior. With automatic properties as
>> they are currently implemented you could write:
>>
>>     public $isEnabled {
>>         get();
>>         set($isEnabled) { $this->__isEnabled = (bool) $isEnabled; }
>>     }
>>
>> This is closer to what I actually want to do, but it relies on using
>> $this->__isEnabled, which is really just an implementation detail.
>>
>> Instead, I would rather want to have access to the "underlying" property:
>>
>>     public $isEnabled {
>>         get();
>>         set($isEnabled) { $this->isEnabled = (bool) $isEnabled; }
>>     }
>>
>> I know that the wording is a bit vague; another way to put it, is that
>> the above inverts the current shadowing behavior:
>>
>> In the current implementation, if there exists a "plain" property and
>> an "accessor" property with the same name, then the plain property
>> shadows the accessor property. As you say, this is to help
>> lazy-loading. I don't really buy the argument about lazy-loading,
>> because I don't think that the small perf difference between going
>> trough an accessor and accessing a plain property is really relevant
>> in that context (especially as lazy-loading would have required a
>> method otherwise).
>>
>> What I'd rather see is the reverse behavior: An accessor property
>> shadows a plain property, so that the plain property is only
>> accessible from within the accessor methods. This would allow you to
>> write code like in the last example above and I think it would also
>> make automatic properties more meaningful (you could store the state
>> in a property with the same name; also nicely integrating with
>> serialization and debugging).
>>
>> I know that you (Clint) want to create a hard distinction between
>> plain properties and accessor properties, but I think that making it
>> more smooth juts integrated better with PHP. I already noticed several
>> people who, after reading the RFC, tried to write code where they
>> access the property from within the accessor. It seems to me that
>> people think it should work. The current behavior where you can shadow
>> the accessor property by assigning a property of the same name seems
>> rather obscure to me.
>>
>> This is the feedback I have for now. Looking forward to your thoughts
>> on the manner.
>> Nikita
>>
>> --
>> PHP Internals - PHP Runtime Development Mailing List
>> To unsubscribe, visit: http://www.php.net/unsub.php
>>
>>



-- 
Etienne Kneuss
http://www.colder.ch

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to