Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:68041 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 39681 invoked from network); 3 Jul 2013 13:04:36 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 3 Jul 2013 13:04:36 -0000 Authentication-Results: pb1.pair.com smtp.mail=brianofish@gmail.com; spf=pass; sender-id=pass Authentication-Results: pb1.pair.com header.from=php@bof.de; sender-id=pass Received-SPF: pass (pb1.pair.com: domain gmail.com designates 209.85.214.45 as permitted sender) X-PHP-List-Original-Sender: brianofish@gmail.com X-Host-Fingerprint: 209.85.214.45 mail-bk0-f45.google.com Received: from [209.85.214.45] ([209.85.214.45:40123] helo=mail-bk0-f45.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 7A/41-30639-36124D15 for ; Wed, 03 Jul 2013 09:04:36 -0400 Received: by mail-bk0-f45.google.com with SMTP id je9so59634bkc.4 for ; Wed, 03 Jul 2013 06:04:32 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:to:cc:subject:date:message-id:user-agent:in-reply-to :references:mime-version:content-transfer-encoding:content-type; bh=56mZ9PcM8d3+1js7JZver2Ol6gpC6xsBtYXNYnVD1AY=; b=H5jUB+MFl2C4Wv745NUw/tiQ59RbekAYo3qQ2M1zfrVeWqdoaPTFCKC9/d3rns736B CmXbnzC0E6abaZRGWyleUb276Odv6NgWQcaFEjetSiQggbI8y+BK3gaRseoTLnKGM9WK Teb2p9zyffp7qMXCOdPORsFYWSkgVLq4MfHq0tgZrNg+aXqnzJZweZ/3cLJ48uV7uwTf mb9+GzqzeiA2NhLUa794oBI/cSvLMHEIgrs9mn/noJOOaJXsAeHgR5Y5fGTYPDTgJHjp LmMcyzs3YoOCnYkQ9w+ynVfxcBHh2OKaP39UC8RRfLSAV9eDF92g0bx26AFKgYQQ1lrq HPsA== X-Received: by 10.204.228.207 with SMTP id jf15mr160947bkb.16.1372856672649; Wed, 03 Jul 2013 06:04:32 -0700 (PDT) Received: from rofl.localnet (p5DCB36A9.dip0.t-ipconnect.de. [93.203.54.169]) by mx.google.com with ESMTPSA id px7sm13690422bkb.9.2013.07.03.06.04.30 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 03 Jul 2013 06:04:31 -0700 (PDT) To: internals@lists.php.net Cc: Terence Copestake Date: Wed, 03 Jul 2013 15:04:28 +0200 Message-ID: <1464204.klkn4uHNEk@rofl> User-Agent: KMail/4.10.4 (Linux/3.9.8-k10-bof; KDE/4.10.4; x86_64; ; ) In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="iso-8859-1" Subject: Re: [PHP-DEV] New feature: sequential constructors From: php@bof.de (Patrick Schaaf) For what it's worth, some time ago I prototyped something like that, wi= thout=20 modifying the language, in the form of a "Universal" class that you may= =20 inherit from without defining __contruct/__destruct yourself. See class definition below. In a using class (herarchy) define static m= ethods=20 _pre_init, _post_init, _pre_exit and _post_exit. They will receive the=20= instance as their sole argument. __construct first calls _pre_init up t= he=20 inheritance chain, then _post_init on the way back down; likewise __des= truct=20 calls _pre_exit and _post_exit In the current form it is only moderately useful, because it doesn't su= pport=20 constructor arguments. These throw up the question of how to pass them = to the "sequential" constructors, and what these would then usefully be able t= o do=20 with them... best regards Patrick class Universal { static private $_universal_pre_inits =3D []; static private $_universal_post_inits =3D []; static private $_universal_pre_exits =3D []; static private $_universal_post_exits =3D []; public function __construct() { $class =3D get_class($this); $initclass =3D $class.'=B0universal_init'; if (!class_exists($initclass, false)) Universal::_universal_inits_and_exits($class); $initclass::_universal_init($this); } public function __destruct() { $initclass =3D get_class($this).'=B0universal_init'; $initclass::_universal_exit($this); } final protected function _universal_inits_and_exits($class) { $pre_inits =3D []; $post_inits =3D []; $pre_exits =3D []; $post_exits =3D []; $c =3D new ReflectionClass($class); try { $m =3D $c->getMethod('_pre_init'); if ($m->class =3D=3D $class) $pre_inits[] =3D [ $class, '_pre_init' = ]; $m =3D $c->getMethod('_pre_exit'); if ($m->class =3D=3D $class) $pre_exits[] =3D [ $class, '_pre_exit' = ]; } catch (Exception $e) {}; $parent =3D get_parent_class($class); if ($parent && $parent !=3D 'Universal') { if (!class_exists($parent.'=B0universal_init', = false)) Universal::_universal_inits_and_exits($= parent); $pre_inits =3D array_merge($pre_inits, self:: $_universal_pre_inits[$parent]); $pre_exits =3D array_merge($pre_exits, self:: $_universal_pre_exits[$parent]); $post_inits =3D array_merge($post_inits, self::= $_universal_post_inits[$parent]); $post_exits =3D array_merge($post_exits, self::= $_universal_post_exits[$parent]); } try { $m =3D $c->getMethod('_post_init'); if ($m->class =3D=3D $class) $post_inits[] =3D [ $class, '_post_init= ' ]; $m =3D $c->getMethod('_post_exit'); if ($m->class =3D=3D $class) $post_exits[] =3D [ $class, '_post_exit= ' ]; } catch (Exception $e) {}; self::$_universal_pre_inits[$class] =3D $pre_inits; self::$_universal_pre_exits[$class] =3D $pre_exits; self::$_universal_post_inits[$class] =3D $post_inits; self::$_universal_post_exits[$class] =3D $post_exits; $code =3D "class {$class}=B0universal_init extends {$cl= ass}{"; $code .=3D 'static protected function _universal_init($= o){'; foreach (array_merge($pre_inits, $post_inits) as $init)= $code .=3D "{$init[0]}::{$init[1]}(\$o);"; $code .=3D '} static protected function _universal_exit= ($o){'; foreach (array_merge($pre_exits, $post_exits) as $exit)= $code .=3D "{$exit[0]}::{$exit[1]}(\$o);"; $code .=3D '}}'; eval($code); } } On Wednesday 03 July 2013 13:45:57 Terence Copestake wrote: > Hello, all. >=20 > On one or two occasions I've encountered a problem when designing a b= ase > class, where I wish to implement important set-up functionality in th= e > constructor, but am limited in how to ensure that the base constructo= r > functionality is unmolested whilst not restricting any inheriting cla= sses > in their use of a constructor, as would be the case when using the fi= nal > keyword. I also don't feel 100% comfortable trusting the inheriting c= lass > to call the parent constructor. >=20 > The idea I'm presenting for discussion here is to have some kind of > (keyword-driven?) hierarchy for constructors, whereby it's possible t= o have > for example sequential constructors, using syntax similar to: >=20 > ... public sequential function __construct($ ... >=20 > In this scenario, constructors defined as sequential are, as the name= > implies, called in sequence. >=20 > If the introduction of a new keyword is problematic, perhaps this sam= e > behaviour could be enacted in cases where an inheriting class has a > constructor and the base class' constructor is defined as final i.e. = rather > than causing an error, the final constructor is executed first, follo= wed by > any other constructors in the hierarchy. >=20 > If this keyword is introduced, perhaps it this idea could also be exp= anded > to allow for sequential methods in general, which would behave simila= rly - > and may be a gateway to function overloading (or similar behaviour). >=20 > I'm open to people pointing out design flaws/implementation difficult= ies > with this; pull no punches. >=20 > Thanks.