rfc:object_cast_magic
no way to compare when less than two revisions
Differences
This shows you the differences between two versions of the page.
Previous revisionNext revision | |||
— | rfc:object_cast_magic [2012/03/04 01:02] – change title ircmaxell | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ===== Request for Comments: Object Cast and Assign Magic Methods ===== | ||
+ | * Version: 0.1 | ||
+ | * Date: 2012-02-28 | ||
+ | * Author: Anthony Ferrara < | ||
+ | * Status: In Draft | ||
+ | |||
+ | ===== Introduction ===== | ||
+ | |||
+ | Currently, the Zend Engine exposes several methods to PECL extensions and internal classes to control how internal objects behave when casting to primitives, and when assigning to the variable that used to hold the object. | ||
+ | |||
+ | It should be noted, that this requires no engine changes to implement. | ||
+ | ===== Use Cases ===== | ||
+ | |||
+ | ==== Scalar Wrapping ==== | ||
+ | |||
+ | One use-case for this functionality is in creating wrapper classes for scalar values. | ||
+ | |||
+ | * Creating strict-typing functionality with entirely user-land code (having a variable that until unset cannot be assigned to with anything except an integer for example) | ||
+ | * Having object code be compatible with existing scalar-typed code. An example would be SplFixedArray would be enabled to be passed to any function (including internal functions) that expect arrays. | ||
+ | * Creating new semi-primitive types with functional limitations applied. | ||
+ | * Creating constant (const) variables that can be written to once (on creation), but not again. | ||
+ | |||
+ | ==== Boolean Logic ==== | ||
+ | |||
+ | Right now, when you use an object in a boolean context, it always evaluates to // | ||
+ | |||
+ | ==== Providing Backwards Compatibility ==== | ||
+ | |||
+ | Quite a few systems depend on primitives to represent data structures. | ||
+ | |||
+ | ===== Proposal and Patch ===== | ||
+ | |||
+ | This RFC proposes two new magic methods to be called when the internal object handlers are invoked: | ||
+ | |||
+ | mixed __castTo(string $type) | ||
+ | bool __assign(mixed $newValue) | ||
+ | |||
+ | ==== 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 " | ||
+ | |||
+ | When the get handler is called, the //castTo// method is invoked with the parameter "// | ||
+ | |||
+ | When the set handler is called, the //assign// method is invoked with the parameter of the new value. | ||
+ | |||
+ | ==== Example Triggers ==== | ||
+ | |||
+ | <?php | ||
+ | | ||
+ | | ||
+ | $obj = $obj + 1; // same as above | ||
+ | $obj |= 5; // triggers __castTo(" | ||
+ | | ||
+ | $obj = 5; // triggers __assign(5) | ||
+ | $obj = array(1, 2, 3); // triggers __assign(array(1, | ||
+ | $obj = new StdClass; // triggers __assign(new StdClass) | ||
+ | |||
+ | if ($obj) // triggers __castTo(" | ||
+ | |||
+ | |||
+ | A proof of concept patch is available here: [[https:// | ||
+ | |||
+ | ==== __toString ==== | ||
+ | |||
+ | The // | ||
+ | |||
+ | Eventually, // | ||
+ | |||
+ | ==== Example ==== | ||
+ | |||
+ | <?php | ||
+ | | ||
+ | class MyInteger { | ||
+ | protected $value; | ||
+ | public function __construct($value = 1) { | ||
+ | $this-> | ||
+ | } | ||
+ | public function __castTo($type) { | ||
+ | switch ($type) { | ||
+ | case ' | ||
+ | case ' | ||
+ | return $this-> | ||
+ | case ' | ||
+ | return (float) $this-> | ||
+ | case ' | ||
+ | return (string) $this-> | ||
+ | default: | ||
+ | throw new LogicException(' | ||
+ | } | ||
+ | } | ||
+ | public function __assign($value) { | ||
+ | if (is_numeric($value)) { | ||
+ | $this-> | ||
+ | return; | ||
+ | } | ||
+ | return false; | ||
+ | } | ||
+ | } | ||
+ | | ||
+ | $foo = new MyInteger(1); | ||
+ | $foo = 2 + 2; | ||
+ | // $foo is still an object, with $value = 4 | ||
+ | $foo++; | ||
+ | // $foo is still an object, with $value = 5 | ||
+ | $foo = floor($foo); | ||
+ | // $foo is still an object, with $value = 5 (since floor causes a cast to float, and then assignment causes a cast back to int) | ||
+ | $foo = array(); | ||
+ | // $foo is now an array, since is_numeric fails | ||
+ | |||
+ | ===== Further reading ===== | ||
+ | |||
+ | * https:// | ||
+ | * https:// | ||
+ | * https:// | ||
+ | * https:// | ||
+ | |||
+ | ===== Questions ===== | ||
+ | How would this RFC affect: | ||
+ | |||
+ | resources | ||
+ | |||
+ | streams | ||
+ | |||
+ | filters | ||
+ | |||
+ | ... | ||
rfc/object_cast_magic.txt · Last modified: 2017/09/22 13:28 by 127.0.0.1