Req #46506 [Opn]: readonly attribute for (public) class variables

From: Date: Wed, 25 Jan 2012 08:11:40 +0000
Subject: Req #46506 [Opn]: readonly attribute for (public) class variables
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-166773@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=46506&edit=1

 ID:                 46506
 User updated by:    glideraerobatics at hotmail dot com
 Reported by:        glideraerobatics at hotmail dot com
 Summary:            readonly attribute for (public) class variables
 Status:             Open
 Type:               Feature/Change Request
-Package:            Feature/Change Request
+Package:            *General Issues
-PHP Version:        5.3.0alpha2
+PHP Version:        5.4
 Block user comment: N
 Private report:     N

 New Comment:

Changed affected PHP version.


Previous Comments:
------------------------------------------------------------------------
[2012-01-24 23:12:32] luke at cywh dot com

I just want the "readonly" keyword to protect a property from being written to 
from the outside. I still want to write to the property from within the class.

Here's a simple example of how it could be used:

class Parent
{
    readonly public $children = array();

    public function addChild($childName)
    {
        $this->children[] = ucwords(strtolower($childName));
    }
}

$parent = new Parent;
$parent->addChild("billy");

$count = count($parent->children); // You can do this

print "Parent has $count children\n";

$name = $parent->children[0]; // You can even do this

print "Parent's first child's name is $name\n";

$parent->children[0] = "BILLY"; // But you can't do this
$parent->children[] = "BOB"; // Or this
$parent->children = NULL; // Or this
unset($parent->children); // Or this


The above example frees you from having to do this:

class Parent
{
    protected $children = array();

    public function addChild($childName)
    {
        $this->children[] = ucwords(strtolower($childName));
    }

    public function hasChild($index)
    {
        return isset($this->children[$index]);
    }

    public function getChild($index)
    {
        return $this->children[$index];
    }

    public function childCount()
    {
        return count($this->children);
    }
}


I've had to write MANY classes like this. The has/isset, get, and count 
functions are virtually all the same.

Some people have even resorted to using __get and __set:

http://stackoverflow.com/questions/402215/php-readonly-properties

The __get and __set magic functions are slow, so much so you're better off 
making your own getters and setters, which is multiplied by the number of 
properties you need like this in the class.

I would recommend the following definitions:

readonly public = read for public, write for protected
readonly protected = read for protected, write for private

I think this should satisfy most cases.

------------------------------------------------------------------------
[2009-07-12 13:27:08] mickael at lupusmic dot org

I guess the readonly keyword in C# is wrong. It hasn't to disallow variance of the attribute,
but the setting from outside the object. Readonly is opposite to constness of a variable. For
example, DOMDocument::doctype isn't constant.

What you think about, it's a dynamic const attribute, in opposite to static one.

So said, a readonly is like a const attribute, but isn't. And it doesn't deserve a scope
qualifier, it can only be public.

For example :

class thing
{
	readonly	$status = 'instantiation' ;

	public		function __construct()
	{
		// do init stuff

		$this->status = 'instantiate' ;
	}

	public		function invalidate()
	{
		// do stuf
		$this->status = 'invalid' ;
	}
}

// Usage
$o = new thing ;
echo $o->status ; // display 'instantiation'
$o->status = 'forced' ; // throw an error E_FATAL

$o->invalidate() ; // do stuff then set readonly status attribute

------------------------------------------------------------------------
[2008-11-06 14:11:42] glideraerobatics at hotmail dot com

Description:
------------
Here is a description of this feature in C#:
http://blog.paranoidferret.com/index.php/2007/09/12/csharp-tutorial-the-readonly-keyword/

In a nutshell it allows you to create classes with public variables that are readonly and can only
be written to / initialized by the contructor of the class itself.

This allows the creation of simple objects without having using accessor methods to protect the
internal data that was validated and initialized during construction from corruption.

Note: bug http://bugs.php.net/bug.php?id=39467 is
about a similar problem but the proposed solution is not quite right.

Reproduce code:
---------------
class Person
{
  public readonly $name = null;
  public readonly $age = null;
  public readonly $weight = null;

  public function __construct($name, $age, $weight) {
  {
    if (!isAgeToWeightRatioSane($age, $weight)) {
      throw new InvalidArgumentException("Invalid age to weight ratio: $age : $weight");
    }
    // TODO: other sanity checks here.
    $this->name = $name;
    $this->age = $age;
    $this->weight = $weight;
  }
}


$person = new Person('Joe', 22, 100);

$person->age = 33; // throws a yet to be named exception





------------------------------------------------------------------------



-- 
Edit this bug report at https://bugs.php.net/bug.php?id=46506&edit=1


Thread (11 messages)

« previous php.bugs (#166773) next »