rfc:propertygetsetsyntax

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
rfc:propertygetsetsyntax [2010/04/25 00:31] – Updated some variable names to match the PHP manual for __get and __set. lieutenantclonerfc:propertygetsetsyntax [2017/09/22 13:28] (current) – external edit 127.0.0.1
Line 1: Line 1:
 ====== Request for Comments: Property get/set syntax ====== ====== Request for Comments: Property get/set syntax ======
-  * Version: 0.1+  * Version: 0.3
   * Date: 2009-09-13   * Date: 2009-09-13
   * Author: Dennis Robinson <president at basnetworks dot net>   * Author: Dennis Robinson <president at basnetworks dot net>
Line 43: Line 43:
     }     }
 }; };
 +</code>
  
 +<code php>
 $sheet = new TimeSheet(); $sheet = new TimeSheet();
 $sheet->foo = 12;// Stored as 43200 $sheet->foo = 12;// Stored as 43200
Line 49: Line 51:
 </code> </code>
  
-In the above example, the TimeSheet class can store a set of time periods.  When accessing the properties of the class, you give and receive hours, yet the time periods are stored as seconds in the $time_list array.  %%__%%get() and %%__%%set() work great here because the same code is applied to every property.+In the above example, the TimeSheet class can store a set of time periods.  When accessing the properties of the class, you give and receive hours, yet the time periods are stored as seconds in the $time_list array.  The magic methods %%__%%get() and %%__%%set() work great here because the same code is applied to every property.
  
 What if we want totally different code to apply to each property? What if we want totally different code to apply to each property?
Line 97: Line 99:
     }     }
 }; };
 +</code>
  
 +<code php>
 $time = new TimePeriod(); $time = new TimePeriod();
 $time->seconds = 12;// Stored as 12 $time->seconds = 12;// Stored as 12
Line 107: Line 111:
 </code> </code>
  
-In the above example, the code of the %%__%%get() and %%__%%set() methods quickly becomes very large, complicated, and difficult to read.  Imagine how cumbersome the code would get adding the properties days, weeks, months, and years.  What if we also wanted to add some other properties?+In the above example, the code in the %%__%%get() and %%__%%set() methods quickly becomes very large, complicated, and difficult to read.  Imagine how cumbersome the code would get adding the properties days, weeks, months, and years.  What if we also wanted to add other properties?
  
 **__Broken Inheritance__** **__Broken Inheritance__**
  
-Now what happens if a second class extends this class.  If the extending class were to define an empty %%__%%get() and %%__%%set() method, the properties would cease to exist in the child class.  This goes against the principles of inheritance, as something that once existed in the parent, no longer does in the child.  By using properties, once a property is definedit is guaranteed to exist in all child classes, with the same or greater visibility.+Now what happens if a second class extends this class.  If the extending class were to define an empty %%__%%get() and %%__%%set() method, the properties would cease to exist in the child class.  This goes against the principles of inheritance, as something that once existed in the parent, no longer does in the child.  By using a proper property syntax, once a property is defined it would be guaranteed to exist in all child classes, with the same or greater visibility.
  
 ===== Properties in C# ===== ===== Properties in C# =====
Line 117: Line 121:
 ==== Why do we care about C#? ==== ==== Why do we care about C#? ====
  
-The current implementations of getters and setters, or properties in various programming languages are almost all have a different syntax.  In order to avoid confusing users, an existing syntax should be followed as closely as possible.  C#'s syntax is often similar to PHP's making it a good reference point.  Additionally, C# has a clean, clear and easily scanned syntax for properties.+The current implementations of getters and setters, or propertiesin various programming languages almost all have a different syntax.  In order to avoid confusing users, an existing syntax should be followed as closely as possible.  PHP's syntax is often similar to C#'s making it a good reference point.  Additionally, C# has a clean, clear and easily scanned syntax for properties.
  
 ==== C# Syntax ==== ==== C# Syntax ====
Line 157: Line 161:
     private $seconds;     private $seconds;
  
 +    // Properties are implemented using the "property" keyword, just like functions/methods use the "function" keyword
     public property Hours     public property Hours
     {     {
Line 172: Line 177:
 </code> </code>
  
-==== Read-Only And Write-Only Properties ====+Note that "get" and "set" as seen above would become new keywords.  Alternatively, "get" and "set" could be made to only have meaning if they are in a prototype, similar to the current type hinting syntax that exists in php-trunk.
  
-A property can be read-writeread-only or write-only.  This example shows the latter two.+**__Alternative Syntax__** 
 + 
 +The syntax above attempts to match the syntax of C# propertiesas well as PHP method declarations as much as possible.  An alternative syntax could look like the following:
  
 <code php> <code php>
Line 181: Line 188:
     private $seconds;     private $seconds;
  
-    public property Minutes+    // Looks less like a function and more like a class member 
 +    // This creates yet another property syntax by moving away from the C# syntax too much 
 +    public $Hours
     {     {
-        set { $this->minutes = $value * 60; } +        get { return $this->seconds / 3600; } 
-    }+        set { $this->seconds = $value * 3600; }// The variable $value holds the incoming value to be "set" 
 +    };// Note the semi-colon here 
 +}; 
 +</code> 
 + 
 +In this syntax, a semi-colon exists at the end of the property definition.  This was suggested by Kalle Nielsen, as it would be simpler to implement into the current implementation of class members in the PHP interpreter. 
 + 
 +**__Alternative Syntax Suggested By jbondc__** 
 + 
 +<code php> 
 +property Hours { 
 + get { return $this->seconds / 3600; } 
 + set { $this->seconds = $value * 3600; } // The variable $value holds the incoming value to be "set" 
 +
 + 
 +class TimePeriod 
 +
 +    private $seconds; 
 + 
 +    public [Hours] $hours; 
 +
 +</code> 
 + 
 +This syntax would favor re-use similar to traits by injecting the set/get code. 
 + 
 +The implementation would add the keywords 'property', _PROPERTY_, the '[', ']' tokens and the 'readonly' property as part of Spl. 
 + 
 +A read-only property could be defined in the following ways: 
 + 
 +<code php> 
 +// Spl property 
 +property readonly 
 +    final set { throw Exception(__PROPERTY__ . " is read-only.");
 +
 + 
 +// Read-only property #1 
 +property MyHours1 extends Hours  { 
 +     use readonly; 
 +
 + 
 +// Read-only property #2 
 +property MyHours2 extends Hours  { 
 + set { throw Exception(__PROPERTY__ . " is read-only.");
 +
 + 
 +// Read-only property #3 (if you don't want an exception) 
 +property MyHours3 extends Hours  { 
 + set { trigger_error(__PROPERTY__ . " is read-only.", E_USER_ERROR);
 +
 +</code> 
 + 
 +Another approach, to reserve the '[', ']' tokens for annotations or something else could be: 
 + 
 +<code php> 
 +// property as some kind of trait 
 +class TimePeriod 
 +
 +    private $seconds; 
 + 
 +    public {use Hours;} $hours; 
 +
 +</code> 
 + 
 +==== Read-Only And Write-Only Properties ==== 
 + 
 +A property can be read-write, read-only or write-only.  This example shows the latter two: 
 + 
 +<code php> 
 +class TimePeriod 
 +
 +    private $seconds;
  
 +    // This property has no "set" method, and therefore is read-only
     public property Hours     public property Hours
     {     {
         get { return $this->seconds / 3600; }         get { return $this->seconds / 3600; }
 +    }
 +
 +    // This property has no "get" method, and therefore is write-only
 +    public property Minutes
 +    {
 +        set { $this->seconds = $value * 60; }
     }     }
 }; };
Line 203: Line 289:
 **__What about the readonly keyword?__** **__What about the readonly keyword?__**
  
-There has been talk about adding a "readonly" keyword to class members in PHP, so why not use it to define read-only properties?  The short answer is, they are not exactly the same thing.  When a property without a set method (a "read-only" property) is overloaded in a child class, the set method can then be implemented and used.  However, if that property was set to read-only using the readonly keyword, the child class would not be allowed to implement a set method.+There has been talk about adding a "readonly" keyword to class members in PHP, so why not use it to define read-only properties?  The short answer is, the readonly keyword does not provide the same functionality.  When a property without a set method (a "read-only" property) is overloaded in a child class, the set method can then be implemented and used.  However, if that property was set defined using the readonly keyword, the child class would not be allowed to implement a set method. 
 + 
 +The following is an example of using the "readonly" keyword with a property: 
 +<code php> 
 +class TimePeriod 
 +
 +    private $seconds; 
 + 
 +    public readonly property Hours 
 +    { 
 +        get { return $this->seconds / 3600; } 
 +    } 
 +}; 
 + 
 +class HalfTimePeriod extends TimePeriod 
 +
 +    public property Hours 
 +    { 
 +        // The get method is being overloaded 
 +        set { return ($this->seconds / 3600) / 2; }// Error, properties with the readonly keyword cannot have a set method 
 +    } 
 +}; 
 +</code>
  
 Additionally, there is no talk of a "writeonly" keyword for PHP, so write-only properties would not be possible. Additionally, there is no talk of a "writeonly" keyword for PHP, so write-only properties would not be possible.
Line 234: Line 342:
 Interfaces may define property declarations, without a body.  The purpose of this is to define properties that must exist in an implementing class, and indicate if they are read-write, read-only, or write-only. Interfaces may define property declarations, without a body.  The purpose of this is to define properties that must exist in an implementing class, and indicate if they are read-write, read-only, or write-only.
  
-When a class implements an interface that has a read-only property, it can add in a set method to turn the property into a read-write property.  The inverse is also true for implementing an interface with a write-only property.  This is because interfaces are to enforce what //should be// in a class, and not what //should not be// in a class.+When a class implements an interface that defines a read-only property, it can add in a set method to turn the property into a read-write property.  The inverse is also true for implementing an interface with a write-only property.  This is because interfaces are designed to enforce what //should be// in a class, and not what //should not be// in a class.
  
 <code php> <code php>
Line 259: Line 367:
 ==== Overloading Properties ==== ==== Overloading Properties ====
  
-Properties can be overloaded in extending classes.  An overloaded property can replace an existing get or set declaration without touching the other, replace both the get and set declarations, or add an omitted get or set declaration turning the property into a read-write property.  Additionally, a property may have its visibility increased through overloading.  Get or set declarations cannot be removed by the child class in any way.+Properties can be overloaded in extending classes.  An overloaded property can replace an existing get or set declaration without touching the other, replace both the get and set declarations, or add an omitted get or set declaration turning the property into a read-write property.  Additionally, a property may have its visibility increased through overloading.  Get or set declarations cannot be removed or hidden by the child class in any way.
  
 <code php> <code php>
Line 299: Line 407:
     public property Minutes     public property Minutes
     {     {
-        // A set method is adding, turning this property into a read-write property instead of read-only+        // A set method is added, turning this property into a read-write property instead of read-only
         set { $this->seconds = $value * 60; }         set { $this->seconds = $value * 60; }
     }     }
Line 305: Line 413:
     public property Milliseconds     public property Milliseconds
     {     {
-        // A property method can be made more visible in a child class, just like regular PHP methods +        // A property method can have its visibility increased in a child class, just like regular PHP methods 
-        // This method is now public instead of private+        // This method is now public instead of protected
         public set         public set
         {         {
-            // You can access a base class property explicitly, just like accessing a base class member or method+            // You can access a base class property explicitly, just like accessing a base class member or method (parent:: could also be used here)
             TimePeriod::$Milliseconds = $value;             TimePeriod::$Milliseconds = $value;
         }         }
Line 318: Line 426:
 ==== Final Properties ==== ==== Final Properties ====
  
-Properties declared final are not able to be overloaded in a child class, just like final methods.+Properties declared final are not allowed to be overloaded in a child class, just like final methods.
  
 <code php> <code php>
Line 331: Line 439:
     }     }
 }; };
-</code> 
  
-<code php> 
 class HalfTimePeriod extends TimePeriod class HalfTimePeriod extends TimePeriod
 { {
Line 342: Line 448:
     {     {
         get { return ($this->seconds / 3600) / 2; }         get { return ($this->seconds / 3600) / 2; }
 +    }
 +};
 +</code>
 +
 +**__Final property methods__**
 +
 +The get or set method of a property can be declared "final" independently of each other.  This would allow for one of them to be overloaded, but not the other.
 +
 +<code php>
 +class TimePeriod
 +{
 +    private $seconds;
 +
 +    // Notice there is no "final" keyword on the property declaration
 +    public property Hours
 +    {
 +        final get { return $this->seconds / 3600; }// Only the get method is declared final
 +        set { $this->seconds = $value * 3600; }
 +    }
 +};
 +
 +class HalfTimePeriod extends TimePeriod
 +{
 +    private $seconds;
 +
 +    public property Hours
 +    {
 +        get { return ($this->seconds / 3600) / 2; }// This attempt to overload the get method of the "Hours" will throw an error
 +                                                   // because it was declared final in the base class
 +        set ( $this->seconds = ($value * 3600) * 2; )// This would be OK
     }     }
 }; };
Line 364: Line 500:
  
 <code php> <code php>
-// Accessing the static property is the same as accessing a static class member+// Accessing static property is the same as accessing a static class member
 TimePeriod::$Hours = 12;// Stored as 43200 TimePeriod::$Hours = 12;// Stored as 43200
 echo TimePeriod::$Hours;// Outputs 12 echo TimePeriod::$Hours;// Outputs 12
 </code> </code>
 +
 +===== Implementation =====
 +
 +An implementation of this proposal is being worked on by Clint Priest <phpdev at zerocue dot com> Information about implementation details can be found here: https://wiki.php.net/rfc/propertygetsetsyntax-as-implemented
  
 ===== References ===== ===== References =====
Line 381: Line 521:
   * [[http://msdn.microsoft.com/en-us/library/x9fsa0sw%28VS.80%29.aspx|Properties (C# Programming Guide)]]   * [[http://msdn.microsoft.com/en-us/library/x9fsa0sw%28VS.80%29.aspx|Properties (C# Programming Guide)]]
   * [[http://msdn.microsoft.com/en-us/library/75e8y5dd%28VS.80%29.aspx|Asymmetric Accessor Accessibility (C# Programming Guide)]]   * [[http://msdn.microsoft.com/en-us/library/75e8y5dd%28VS.80%29.aspx|Asymmetric Accessor Accessibility (C# Programming Guide)]]
 +  * [[http://msdn.microsoft.com/en-us/library/ms229054.aspx|Choosing Between Properties and Methods (MSDN)]]
 +  * [[http://msdn.microsoft.com/en-us/library/ms229006.aspx|Property Design (MSDN)]]
 +  * [[http://c2.com/cgi/wiki?UniformAccessPrinciple|Uniform Access Principle (C2 wiki)]]
 +  * [[http://en.wikipedia.org/wiki/Uniform_access_principle|Uniform Access Principle (Wikipedia)]]
  
 ===== Changelog ===== ===== Changelog =====
Line 391: Line 535:
   - 2010-04-24 Dennis Robinson: Updated some incorrect code examples in the section "The Problem".   - 2010-04-24 Dennis Robinson: Updated some incorrect code examples in the section "The Problem".
   - 2010-04-24 Dennis Robinson: Fleshed out the "The Current Solution" section description.   - 2010-04-24 Dennis Robinson: Fleshed out the "The Current Solution" section description.
 +  - 2010-04-24 Dennis Robinson: Added further clarification to the "What about the readonly keyword?" section description, and added a code example. 
 +  - 2010-04-24 Dennis Robinson: Added an alternative syntax. 
 +  - 2010-04-24 Dennis Robinson: Added an example of property methods being marked final individually. 
 +  - 2010-11-13 Dennis Robinson: Added a note below the basic syntax about new keywords being created. 
 +  - 2010-11-13 Dennis Robinson: Added a semicolon to the "alternative syntax", as suggested by Kalle Nielsen. 
 +  - 2010-11-29 jbondc: Added another alternative syntax 
 +  - 2010-12-01 Dennis Robinson: Added additional links in the "Further Reading" section 
 +  - 2011-12-22 Dennis Robinson: Added "Implementation" section
rfc/propertygetsetsyntax.txt · Last modified: 2017/09/22 13:28 by 127.0.0.1