Parameter checking in 5.2

php.internals

Christian Schneider

19 years ago
In the discussion about parameter checking in 5.2 I proposed to relax the checks a tiny little bit: Don't test static functions (e.g. useful for factory methods) and allow adding default values to functions (the object of the inherited class still accepts the same parameters as the base class). A patch is attached. Example: class Base { static function factory($x) { } function foo($x) { } } class Spezialized extends Base { static function factory() { } # Static method, e.g. factory method function foo($x = null) { } # Default values for specialized class } Regards, - Chris

Jasper Bryant-Greene

19 years ago
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA512 +1 Given that static methods apply to the class and don't have much in the way of inheritance rules, Christian's suggested behaviour makes a lot of sense. Jasper Christian Schneider wrote:
> In the discussion about parameter checking in 5.2 I proposed to relax > the checks a tiny little bit: Don't test static functions (e.g. useful > for factory methods) and allow adding default values to functions (the > object of the inherited class still accepts the same parameters as the > base class). A patch is attached. > > Example: > class Base > { > static function factory($x) { } > function foo($x) { } > } > > class Spezialized extends Base > { > static function factory() { } # Static method, e.g. factory method > function foo($x = null) { } # Default values for specialized class > } > > Regards, > - Chris > > > ------------------------------------------------------------------------ > > Index: Zend/zend_compile.c > =================================================================== > RCS file: /repository/ZendEngine2/zend_compile.c,v > retrieving revision 1.647.2.27.2.18 > diff -u -r1.647.2.27.2.18 zend_compile.c > --- Zend/zend_compile.c 19 Sep 2006 21:36:53 -0000 1.647.2.27.2.18 > +++ Zend/zend_compile.c 20 Sep 2006 19:05:43 -0000 > @@ -1922,13 +1922,12 @@ > } > > /* Checks for constructors only if they are declared in an interface */ > - if ((fe->common.fn_flags & ZEND_ACC_CTOR) && !(proto->common.scope->ce_flags & ZEND_ACC_INTERFACE)) { > + if ((fe->common.fn_flags & (ZEND_ACC_CTOR | ZEND_ACC_STATIC)) && !(proto->common.scope->ce_flags & ZEND_ACC_INTERFACE)) { > return 1; > } > > /* check number of arguments */ > - if (proto->common.required_num_args != fe->common.required_num_args > - || proto->common.num_args > fe->common.num_args) { > + if (proto->common.num_args > fe->common.num_args) { > return 0; > } > > >
- -- Jasper Bryant-Greene Director Album Limited jasper@album.co.nz +64 21 708 334 / 0800 425 286 http://www.album.co.nz/ -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.5-ecc0.1.6 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iFcDBQFFEfIqnqZ4vwo6v1gRCrP0AP4iqczaBXNYGTtooXvP8AKcfwS1tlfHghVa U4EWSFsIMQD/eoAnLN9JeJaqFqIqfttF2Pq4TR1GLHkJdowFKZY7vgc= =DSys -----END PGP SIGNATURE-----

Marcus Börger

19 years ago
Hello Christian, the short form is, use interfaces. And the long form is read the upgrade file and find out to use interfaces :-) best regards marcus Wednesday, September 20, 2006, 12:11:27 PM, you wrote:
> In the discussion about parameter checking in 5.2 I proposed to relax > the checks a tiny little bit: Don't test static functions (e.g. useful > for factory methods) and allow adding default values to functions (the > object of the inherited class still accepts the same parameters as the > base class). A patch is attached.
> Example: > class Base > { > static function factory($x) { } > function foo($x) { } > }
> class Spezialized extends Base > { > static function factory() { } # Static method, e.g. factory method > function foo($x = null) { } # Default values for specialized class > }
> Regards, > - Chris
Best regards, Marcus

Christian Schneider

19 years ago
Marcus Boerger wrote:
> the short form is, use interfaces. And the long form is read the upgrade > file and find out to use interfaces :-)
I don't understand how interfaces are connected to my proposal, please explain. Personally I don't need the strict OO checks for matching parameter lists at all, but as long as they are E_STRICT (or the like) I have no problem with them being done. Nevertheless I would like to relax them just a tiny little bit for signature changes not having an impact of object compatibility. That's why I posted two use cases where the checks IMHO go too far and added a patch to change that. Copy of my message:
>> In the discussion about parameter checking in 5.2 I proposed to relax >> the checks a tiny little bit: Don't test static functions (e.g. useful >> for factory methods) and allow adding default values to functions (the >> object of the inherited class still accepts the same parameters as the >> base class). A patch is attached. > >> Example: >> class Base >> { >> static function factory($x) { } >> function foo($x) { } >> } > >> class Spezialized extends Base >> { >> static function factory() { } # Static method, e.g. factory method >> function foo($x = null) { } # Default values for specialized class >> }
- Chris

Stanislav Malyshev

19 years ago
> Personally I don't need the strict OO checks for matching parameter > lists at all, but as long as they are E_STRICT (or the like) I have no > problem with them being done. Nevertheless I would like to relax them > just a tiny little bit for signature changes not having an impact of > object compatibility.
I agree that allowing to extend method signature (albeit with notice) is a good thing. You could do a number of nice things with it like flexible interfaces receiving variable parameters - still staying with OO. E.g., you can do patterns like this: abstract class Processor() { abstract protected function process(); private function prepare() { /// do something } public function prepare_and_process(/* variable args */) { $this->prepare(); $this->process(/* some args */); } } And extends it overriding only process() function having concrete arguments. Of course, not everybody wants it - some would miss strict control on process parameters - but I don't see why it should not be possible in PHP, for those who wants it. That's why PHP is a dynamic language, I think. Right now if I remove abstract from process() method I can do it - but why couldn't I do it with abstract too? Interfaces don't exactly play nice with it since you can not add code to the interface and can not define visibility for methods.