RE: [PHP-DEV] Proposal: Type Casting User Classes
| From: | Robert Stoll | Date: | Fri, 15 Nov 2013 10:07:56 +0000 |
| Subject: | RE: [PHP-DEV] Proposal: Type Casting User Classes | ||
| References: | 1 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-70154@lists.php.net to get a copy of this message | ||
Hi Chris
> -----Original Message-----
> From: Chris London [mailto:me@chrislondon.co]
> Sent: Thursday, November 14, 2013 7:40 PM
> To: internals@lists.php.net
> Subject: [PHP-DEV] Proposal: Type Casting User Classes
>
> Hey everyone,
>
> I want to get a feel for something I would like to implement into PHP
core.
> I would like to be able to cast objects to my own class types. Similar
to
> already available PHP syntax:
>
> $foo = (string) $bar;
>
> The syntax would look like this:
>
> $foo = (\My\FooObject) $bar;
>
> It would also support:
>
> $foo = ( (\My\FooObject) $bar )->myFooObjectFunction();
>
> I'm still trying to decide what would happen internally and I would like
some
> feedback. I'm thinking of 3 different things it could do:
>
> 1) Directly change the class type, functionally equivalent to:
>
> function castType($object, $type) {
> return unserialize(preg_replace("/^O:[0-9]+:\"[^\"]+\":/i",
> "O:".strlen($type).":\"$type\":", serialize($object)));
> }
[Robert Stoll]
Seems a bad idea to me. Would be slow and is not really a cast but a
conversion.
> 2) Throw a fatal error if the object doesn't match the type trying to be
cast.
[Robert Stoll]
That's what I would expect from a runtime type checking mechanism
> 3) Add a new static magic method called __cast() that would allow the
> developer to decide what happens. Like this:
>
> namespace \My;
>
> class FooObject {
> public static function __cast($foo) {
> // Do stuff here
> return new FooObject;
> }
> }
[Robert Stoll]
This is interesting but goes beyond casts and is a conversion mechanism
again. But would be truly helpful for utility classes like Email etc. (there
was already another discussion about this feature as far as I remember)
> I'm willing to implement this myself if everybody else likes this idea.
> Thanks!
>
> Chris London
You might be interested in my project Type-Safe PHP (TSPHP):
http://tsphp.tutteli.ch
It is far from a real release candidate but that's mostly because I am the
only developer contributing to this project so far (and unfortunately I do
not really have time lately).
Other contributors are welcome ;-)
TSPHP would substitute object casts for you (without the performance penalty
of an additional function call and the use of is_a) but you could emulate it
with a function this way:
function cast($object, $type){
if($object == null || \is_a($object,$type)){
return $object;
}else{
trigger_error('cast error, $object was not of type '.$type);
}
}
I have chosen trigger_error to be consistent with (int), (string) etc. which
trigger an error as well if something goes wrong. Replace it with a throw if
you like.
And use it like this - a one liner as well ;-)
class A{}
class B extends A{}
$a = new B();
$a = cast($a, "A");
Of course, $a will not change its type but is guaranteed to be of type A.
There was a discussion about down casting in another email. That's not
possible with this function since it is a cast and not a conversion. Btw the
Liskov Substitution Principle tells that you should be able to replace your
class with your sub-class without breaking things but not that a class
magically can do the same thing as a sub-class. But you were probably
thinking about a conversion/mapping and fair enough, that might be possible
but there are a lot of cases where this is not as straight forward as you
may think.
Cheers,
Robert