For what it's worth, some time ago I prototyped something like that, without 
modifying the language, in the form of a "Universal" class that you may 
inherit from without defining __contruct/__destruct yourself.

See class definition below. In a using class (herarchy) define static methods 
_pre_init, _post_init, _pre_exit and _post_exit. They will receive the 
instance as their sole argument. __construct first calls _pre_init up the 
inheritance chain, then _post_init on the way back down; likewise __destruct 
calls _pre_exit and _post_exit

In the current form it is only moderately useful, because it doesn't support 
constructor arguments. These throw up the question of how to pass them to the
"sequential" constructors, and what these would then usefully be able to do 
with them...

best regards
  Patrick

class Universal {

        static private $_universal_pre_inits = [];
        static private $_universal_post_inits = [];
        static private $_universal_pre_exits = [];
        static private $_universal_post_exits = [];

        public function __construct() {
                $class = get_class($this);
                $initclass = $class.'°universal_init';
                if (!class_exists($initclass, false))
                        Universal::_universal_inits_and_exits($class);
                $initclass::_universal_init($this);
        }

        public function __destruct() {
                $initclass = get_class($this).'°universal_init';
                $initclass::_universal_exit($this);
        }

        final protected function _universal_inits_and_exits($class) {
                $pre_inits = [];
                $post_inits = [];
                $pre_exits = [];
                $post_exits = [];
                $c = new ReflectionClass($class);
                try {
                        $m = $c->getMethod('_pre_init');
                        if ($m->class == $class)
                                $pre_inits[] = [ $class, '_pre_init' ];
                        $m = $c->getMethod('_pre_exit');
                        if ($m->class == $class)
                                $pre_exits[] = [ $class, '_pre_exit' ];
                } catch (Exception $e) {};

                $parent = get_parent_class($class);
                if ($parent && $parent != 'Universal') {
                        if (!class_exists($parent.'°universal_init', false))
                                Universal::_universal_inits_and_exits($parent);
                        $pre_inits = array_merge($pre_inits, self::
$_universal_pre_inits[$parent]);
                        $pre_exits = array_merge($pre_exits, self::
$_universal_pre_exits[$parent]);
                        $post_inits = array_merge($post_inits, self::
$_universal_post_inits[$parent]);
                        $post_exits = array_merge($post_exits, self::
$_universal_post_exits[$parent]);
                }

                try {
                        $m = $c->getMethod('_post_init');
                        if ($m->class == $class)
                                $post_inits[] = [ $class, '_post_init' ];
                        $m = $c->getMethod('_post_exit');
                        if ($m->class == $class)
                                $post_exits[] = [ $class, '_post_exit' ];
                } catch (Exception $e) {};

                self::$_universal_pre_inits[$class] = $pre_inits;
                self::$_universal_pre_exits[$class] = $pre_exits;
                self::$_universal_post_inits[$class] = $post_inits;
                self::$_universal_post_exits[$class] = $post_exits;

                $code = "class {$class}°universal_init extends {$class}{";
                $code .= 'static protected function _universal_init($o){';
                foreach (array_merge($pre_inits, $post_inits) as $init)
                        $code .= "{$init[0]}::{$init[1]}(\$o);";
                $code .= '} static protected function _universal_exit($o){';
                foreach (array_merge($pre_exits, $post_exits) as $exit)
                        $code .= "{$exit[0]}::{$exit[1]}(\$o);";
                $code .= '}}';
                eval($code);
        }

}
On Wednesday 03 July 2013 13:45:57 Terence Copestake wrote:
> Hello, all.
> 
> On one or two occasions I've encountered a problem when designing a base
> class, where I wish to implement important set-up functionality in the
> constructor, but am limited in how to ensure that the base constructor
> functionality is unmolested whilst not restricting any inheriting classes
> in their use of a constructor, as would be the case when using the final
> keyword. I also don't feel 100% comfortable trusting the inheriting class
> to call the parent constructor.
> 
> The idea I'm presenting for discussion here is to have some kind of
> (keyword-driven?) hierarchy for constructors, whereby it's possible to have
> for example sequential constructors, using syntax similar to:
> 
> ... public sequential function __construct($ ...
> 
> In this scenario, constructors defined as sequential are, as the name
> implies, called in sequence.
> 
> If the introduction of a new keyword is problematic, perhaps this same
> 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, followed by
> any other constructors in the hierarchy.
> 
> If this keyword is introduced, perhaps it this idea could also be expanded
> to allow for sequential methods in general, which would behave similarly -
> and may be a gateway to function overloading (or similar behaviour).
> 
> I'm open to people pointing out design flaws/implementation difficulties
> with this; pull no punches.
> 
> Thanks.

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to