I was playing around with anonymous's suggestion to make any mutations of the object return a new object, and this works, but it's awkward.
<?php
class FruityEnum {
private $valid = array("apple", "banana", "cantaloupe");
private $value;
function __construct($val) {
if (in_array($val, $this->valid)) {
$this->value = $val;
} else {
throw new Exception("Invalid value");
}
}
function __set($var, $val) {
throw new Exception("Use set()!!");
}
function set(FruityEnum &$obj, $val) {
$obj = new FruityEnum($val);
}
function __get($var) { //everything returns the value...
return $this->value;
}
function __toString() {
return $this->value;
}
}
And now to test it:
function mutate(FruityEnum $obj) { // type hinting!
$obj->set($obj, 'banana');
return $obj;
}
$x = new FruityEnum('apple');
echo $x; // "apple"
$y = mutate($x);
echo $x // still "apple"
. $y // "banana"
It works, but you have to use a strange way to change the object:
$obj->set($obj, 'foo');
The only other way I could think to do it would be to use the __set()
method, but that was even worse. You had to do this, which is bloody confusing.
$obj = $obj->blah = 'foo';
In the end, it's probably easier to make the variables private and provide no mutators, so the only way to change a variable's "enum" value would be to create a new one:
echo $obj; // "banana"
$obj = new FruityEnum("cantaloupe");