Request for Comments: Boxing and Unboxing
- Version: 1.0
- Date: 2009-07-06
- Author: Josh Thompson <spam.goes.in.here --at-- gmail.com>
- Status: Under Discussion
- First Published at: http://news.php.net/php.internals/44616
This RFC discusses a new feature for PHP called boxing and includes discussions of related RFCs that would complete the implementation of boxing and unboxing.
Introduction
Boxing and unboxing is a concept from the C# language. The basic idea of boxing in C# is that a value type is implicitly converted to an object type. Unboxing is the opposite and is done explicitly to convert the object back to a value type.
Boxing: Implicit Conversion To Objects
The most obvious use for boxing is function and method type hints. The object type hints could be used to do implicit boxing of variables. Either a new magic method (__box
for example) or a new interface (Boxable
for example) would need to be added to PHP. The boxing method would accept the scalar value and set its internal representation (similar to __wakeup
). The method could either return false (and let PHP handle the failure) or throw an exception (BoxingException
for example) when the supplied value is not valid for the boxing operation.
It would be best for PHP to include as many object versions of scalar types as possible. The boxing functionality could be added to the SPL Types 1) to provide for standard representations of the scalar types. The power to box variables would also be available in userland classes.
It could also be possible to try to perform implicit conversions from one object type to another, but the overhead of this feature may be too much. Consider it as an option only.
Unboxing: Or, Casting To Scalar
The unboxing of variables would need to occur on an explicit cast or on a call to an internal function. The unboxing could be implemented as the RFC for class casting to scalar 2). It already discusses some examples for a new magic method or interface. I propose some more to relate to the unboxing concept (__unbox
for a magic method, and Unboxable
for an interface).
Benefits
The benefits to boxing and unboxing include:
- Only minor modifications required to the current type-hinting implementation (I am only assuming this part).
- The boxing and unboxing ability can be used in userland classes to accomplish “cool things”.
- Get SplTypes and scalar casting in PHP core.
Examples
Example of different int object classes:
<?php class StrictInt //implements Boxable, Unboxable { protected int $value; public function __box($value) { if (!is_int($value)) { //throw new BoxingException('StrictInt does not except non-int values'); return false; } $this->value = $value; } public function __unbox($type, $class = null) { switch ($type) { case (Unboxable::INT): return $this->value; break; case (Unboxable::FLOAT): return (float)$this->value; break; case (Unboxable::STRING): return (string)$this->value; break; default: throw new UnboxingException('StrictInt cannot convert to type: ' . Unboxable::getTypeString($type)); break; } } } class FuzzyInt //implements Boxable, Unboxable { protected $value; public function __box($value) { $this->value = (int)$value; } public function __unbox($type, $class = null) { switch ($type) { case (Unboxable::INT): return $this->value; break; case (Unboxable::FLOAT): return (float)$this->value; break; case (Unboxable::STRING): return (string)$this->value; break; default: throw new UnboxingException('FuzzyInt cannot convert to type: ' . Unboxable::getTypeString($type)); break; } } } function testStrict(StrictInt $value) { $test = (int)$value * 2; echo $test, ' ', $value; } function testFuzzy(FuzzyInt $value) { $test = (int)$value * 2; echo $test, ' ', $value; } testStrict(1); // '2 1' // testStrict(1.5); // error // testStrict('1'); // error // testStrict('one'); // error testFuzzy(1); // '2 1' testFuzzy(1.5); // '2 1' testFuzzy('1'); // '2 1' testFuzzy('one'); // '0 0'
Proposal and Patch
No patch exists for Boxing. The casting to scalar has some patches on its RFC page.
Rejected Features
None
Changelog
2009-07-06: Initial Draft