Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:58082 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 36907 invoked from network); 26 Feb 2012 15:14:48 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 26 Feb 2012 15:14:48 -0000 Authentication-Results: pb1.pair.com header.from=cpriest@zerocue.com; sender-id=pass Authentication-Results: pb1.pair.com smtp.mail=cpriest@zerocue.com; spf=pass; sender-id=pass Received-SPF: pass (pb1.pair.com: domain zerocue.com designates 74.115.204.54 as permitted sender) X-PHP-List-Original-Sender: cpriest@zerocue.com X-Host-Fingerprint: 74.115.204.54 relay-hub202.domainlocalhost.com Received: from [74.115.204.54] ([74.115.204.54:53551] helo=relay-hub202.domainlocalhost.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 23/E0-30711-66C4A4F4 for ; Sun, 26 Feb 2012 10:14:47 -0500 Received: from MBX201.domain.local ([169.254.1.244]) by HUB202.domain.local ([192.168.69.2]) with mapi id 14.01.0355.002; Sun, 26 Feb 2012 10:14:43 -0500 To: Anthony Ferrara , "internals@lists.php.net" Thread-Topic: [PHP-DEV] Object Casting - An Alternative to Type Hinting Thread-Index: AQHM9JcPrX1SK8YtUUCt8RuNMcObRpZPR7kQ Date: Sun, 26 Feb 2012 15:14:42 +0000 Message-ID: <9570D903A3BECE4092E924C2985CE4854FC3AF68@MBX201.domain.local> References: In-Reply-To: Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [192.168.64.23] Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Subject: RE: [PHP-DEV] Object Casting - An Alternative to Type Hinting From: cpriest@zerocue.com (Clint M Priest) I definitely like the idea of being able to cast objects, I've frequently w= ished to be able to cast an object to an array. I would argue against the = single __castTo() and __castFrom() magic methods as large switches get to b= e difficult to find/read and doesn't support separation. I would prefer something along the lines of C++ such as: Cast From: public __construct(Integer $i); Cast To:=20 public Integer(); This would require function overloading (__construct overloading by type) b= ut with Type Hinting already available for function parameters, this could = be done relatively easily I think. Doing this would keep code isolated with smaller functions. -Clint -----Original Message----- From: Anthony Ferrara [mailto:ircmaxell@gmail.com]=20 Sent: Sunday, February 26, 2012 8:57 AM To: internals@lists.php.net Subject: [PHP-DEV] Object Casting - An Alternative to Type Hinting I've gone back and re-read a bunch of the old posts on Type Hinting, and ha= ve come to the conclusion that it won't be done any time soon. Not because it doesn't have merit, but because there are at least a few fun= damental difficulties that are non-trivial to figure out while still keepin= g the usefulness. So, I started thinking of a way that we can work around it. One technique = that has been passed around is to use object wrappers and pass objects inst= ead of scalars. Such as was suggested in: http://marc.info/?l=3Dphp-internals&m=3D119543188808737&w=3D2 One of the problems associated with this, is that before you work with thes= e types, you need to manually cast them back to the native type they repres= ent. We can try to deal with this problem using __toString, but I don't th= ink that's granular enough to really be of much use in solving this problem= ... Another method we could use, is if we supported operator overloading in obj= ects. That way, we could overload the addition operator to handle the oper= ation. However, this becomes quite problematic, since ordering of operatio= ns and interaction with disparate class trees is going to get rather messy = (and extremely fragile) quite quick. Let me throw out another possible solution. What if we added two new magic= methods to objects: public function __castTo($type); public static function __castFrom($value); With these two methods, we could enable type-hinting by using something ver= y similar to auto-boxing. Let me start with a sample implementation: class Integer { protected $value =3D 0; public function __construct($value) { $this->value =3D $value; } public function __castTo($type) { switch ($type) { case 'int': case 'numeric': return $this->value; case 'float': return (float) $this->value; } throw new LogicException('Illegal Cast Operation Performed'); } public static function __castFrom($value) { if (!is_scalar($value)) { throw new LogicException('Illegal Cast Operation Performed'); } return new static((int) $value); } } Now, that enables us to do something like: $int =3D new Integer(2); echo $int + 2; // 4, since __castTo was called with "numeric" echo substr("foobar", 0, $int); // "fo" since __castTo was called with "int= " That demonstrates the __castTo usages. Now for the __castFrom... function foo(Integer $int) { echo $int + 1; } Now, under current rules, calling foo(1) would result in a fatal error. Ho= wever, we could change that to check if the class being type-hinted for has= a __castFrom method on it. If it does, it would attempt to cast the value= into that class. So calling foo(1) would actually internally call `Intege= r::__castFrom(1)`. And since that returns an object of instance Integer, t= he hint would pass. These two additions would solve a few issues with type-hinting. First off,= it solves the "cast to" vs "error if" debate on passing a string in the pl= ace of an integer. In this case, it would be up to the __castFrom() method to determine that (thereby enabling both worlds possibl= e). Second, it solves the problem of having to wrap clumsy APIs around sca= lars for hinting purposes ($foo->getInteger() + 1). Third, it is still completely optional... Fourth, it keeps and tries to em= brace the dynamic type-cohersion nature of PHP... Now, that's not to say it's not without problems. Here are a few that I ca= n think of: 1. How should it deal with references? If I do `function foo(Integer &$int= )`, what should happen? - I would argue that if you're trying to reference, the casting functio= nality should not be expected to work at all. But that introduces some inc= onsistency there. Not sure how to solve that... 2. Should it support casting from one object to another? Meaning if I pass= an SPLInt to something expecting Integer (from two different trees), shoul= d __castFrom be called? - I would argue that yes, it should. That would open the door for comp= atibility layers to be built for cross-framework interaction that happens s= eamlessly regardless of what was passed in. But it could get a bit interes= ting, since that also could wind up having really non-obvious side-effects,= mainly because of object references... 3. Should "class casting" then be supported? We can currently do (int) $foo. Should we then be able to specify a class in the cast instead?= (Integer) $foo? - I like the concept, but that could be a nightmare to implement as it'= s hard to tell if it's a class reference or a constant enclosed in () for t= he parser. And seeing as you can have a constant with the same name as a c= lass, which should take precedence? 4. Should __toString still be called for string contexts? Or would the pre= sence of __castTo then negate the existance of __toString. So if you don't= implement __castTo(), __toString() would still be called for a string cast= . But if you do, __castTo would be called instead... It would then work for backwards compatibility, while enabling __toString = to be eventually deprecated in favor of __castTo (not for a long time mind = you, but eventually, possibly 6 or 7)... What do you think? Anthony -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit:= http://www.php.net/unsub.php