Next revision | Previous revisionNext revisionBoth sides next revision |
rfc:object_cast_magic [2012/02/29 02:16] – created ircmaxell | rfc:object_cast_magic [2012/02/29 02:43] – [Example] ircmaxell |
---|
* Creating new semi-primitive types with functional limitations applied. An example would be the ability to create an integer type that is always less than a configured maximum. Another example would be to create a string type that self-prevents invalid characters (by regex, or otherwise)... | * Creating new semi-primitive types with functional limitations applied. An example would be the ability to create an integer type that is always less than a configured maximum. Another example would be to create a string type that self-prevents invalid characters (by regex, or otherwise)... |
* Creating constant (const) variables that can be written to once (on creation), but not again. (this is sort-of not true, since you can still manually unset() the variable, but it would prevent accidental overwriting) | * Creating constant (const) variables that can be written to once (on creation), but not again. (this is sort-of not true, since you can still manually unset() the variable, but it would prevent accidental overwriting) |
| |
| ==== Boolean Logic ==== |
| |
| Right now, when you use an object in a boolean context, it always evaluates to //TRUE//. By overloading the castTo with boolean type, you can have the object return as true or false. This can be used for implementing validators that can be checked with a simple //if ($valid)// instead of having to proxy to a method. |
| |
==== Providing Backwards Compatibility ==== | ==== Providing Backwards Compatibility ==== |
bool __assign(mixed $newValue) | bool __assign(mixed $newValue) |
| |
When the cast_object handler is called, the __castTo method is invoked with a string representation of the type to be casted to. The return value is then used as the "casted" value. | ==== Handler Behavior ==== |
| |
| When the cast_object handler is called, the //castTo// method is invoked with a string representation of the type to be casted to. The return value is then used as the "casted" value. This would be called when explicitly cast (using //(int)// style syntax), when implicitly cast (passing as a parameter to an internal function expecting a specific type parameter) and when casted to a string (echo $obj;). |
| |
| When the get handler is called, the //castTo// method is invoked with the parameter "//native//". This would indicate that the cast is to a scalar, but the type is up to the class to determine. This is called when a primitive type is needed, but not a specific one. So the normal math operators trigger a get call: (+, -, *, /), in addition to compound operators (++, +=, &=, |=, etc). |
| |
| When the set handler is called, the //assign// method is invoked with the parameter of the new value. The object can then react to this assignment (by setting a new internal state, by throwing an exception, etc). If the object wants to be overwritten, it can return //FALSE//, which will cause the default assignment handler (overwriting the object) to happen. |
| |
| ==== Example Triggers ==== |
| |
| <?php |
| |
| $obj++; // triggers __castTo("native"), followed by __assign($result_from_cast + 1) |
| $obj = $obj + 1; // same as above |
| $obj |= 5; // triggers __castTo("native"), followed by __assign($result_from_cast | 5) |
| |
| $obj = 5; // triggers __assign(5) |
| $obj = array(1, 2, 3); // triggers __assign(array(1, 2, 3)) |
| $obj = new StdClass; // triggers __assign(new StdClass) |
| |
| if ($obj) // triggers __castTo("boolean") |
| |
| |
A proof of concept patch is available here: [[https://gist.github.com/1929587]] (note, this is a POC **ONLY**, there are issues with it, such as memory leaks). | A proof of concept patch is available here: [[https://gist.github.com/1929587]] (note, this is a POC **ONLY**, there are issues with it, such as memory leaks). |
| |
| ==== __toString ==== |
| |
| The //toString// magic method would become redundant, since it is just a limited version of the //castTo// handler (it actually implements the cast_object handler internally). Based on that, any class implementing //castTo// would then ignore a //toString// method if it's defined. For backwards compatibility reasons, if //castTo// is **not** defined on the class (or parent), then //toString// would be executed for any string casts. |
| |
| Eventually, //toString// would be deprecated as duplicate functionality (but not any time soon, as it would still work fine). |
| |
==== Example ==== | ==== Example ==== |
if (is_numeric($value)) { | if (is_numeric($value)) { |
$this->value = (int) $value; | $this->value = (int) $value; |
| return; |
} | } |
return false; | return false; |
* https://wiki.php.net/internals/engine/objects#cast_object | * https://wiki.php.net/internals/engine/objects#cast_object |
| |
===== References ===== | |
| |
* [1] https://secure.wikimedia.org/wikipedia/en/wiki/Weak_reference | |
* [2] https://secure.wikimedia.org/wikipedia/en/wiki/Observer_pattern | |
* [3] http://download.oracle.com/javase/1.4.2/docs/api/java/lang/ref/WeakReference.html | |