2011-09-20 45 views
1

我有一个扩展的类,它的子进一步扩展了任意的次数。每个扩展提供比其前一个更多的功能。值得注意的是,并非所有参数都可以在初始化时提供。它足够复杂,足以保证通过方法传递更多配置选项,然后调用某种build()或configure()方法来为运行做好准备。在PHP中,如何通过层次结构从最大父项中的方法递归调用一种方法?

问题是,层次结构中的每个类都需要一个配置自身的机会,并且需要从父级级联到所有子级。

成功做到这一点,但这个解决方案要求每个类都记得调用它的父方法,否则它会中断。我想从那些可能忘记这样做的人那里去除那个责任。

如何修改此代码以实现此目的?

<?php 

class A { 
    function configure() { 
     print("I am A::configure() and provide basic functionality.<br/>\n");; 
    } 
} 

class B extends A { 
    function configure() { 
     parent::configure(); 
     print("I am B::configure() and provide additional functionality.<br/>\n"); 
    } 
} 

class C extends B { 
    function configure() { 
     parent::configure(); 
     print("I am C::configure() and provide even more functionality.<br/>\n"); 
    } 
} 

$c = new C; 
$c->configure(); 

?> 

输出:

I am A::configure() and provide basic functionality. 
I am B::configure() and provide additional functionality. 
I am C::configure() and provide even more functionality. 

感谢您的帮助! :)

+1

为什么不使用构造函数?毕竟,这就是他们的目标。 –

+0

@Kerrek SB:+1,但将仍然需要调用链中的手动 – zerkms

+0

使用其中之一涉及配置的显著量,足够努力,以适应在构造函数中的所有参数是不是合理的每一个构造。 – Maarx

回答

1

没有声称它很漂亮,我会建议以下。为了简洁起见,我省略了configure()函数。

<?php 

class A { 
    function configure_master() { 
    $init_class = get_class($this); 
    $ancestry = array(); 
    while (! empty($init_class)) { 
     $ancestry[] = $init_class; 
     $init_class = get_parent_class($init_class); 
    } 
    for ($i = count($ancestry) - 1; $i >= 0; $i--) { 
     call_user_func(array($this, $ancestry[$i] . '::configure')); 
    } 
    } 
} 

$c = new C; 
$c->configure_master(); 

我测试了这一点,它的工作原理。 call_user_func($ancestry[$i] . '::configure')也起作用(至少在php 5.3中,这是我测试它的地方),但它依赖于$ this的奇数(对我)范围。我不确定这是可靠的还是将会延续到未来的版本中。鉴于我的知识有限,上面的版本“应该”更加健壮。我建议将所有的“configure()”方法重命名为“configure_local()”或其他类型,并将“configure_master()”重命名为“configure ()”。事实上,这就是我要做的事情,但这是个人品味的问题。

如果您既需要内部方法和外部API保持不变......然后,你就完蛋了,因为基类的方法被重写,但我敢肯定,你知道的。

1

任意数量的继承?我不能说这是我想要采取的一种方式,但是如果您必须这样做,您可能可以在基类中编写一些类型的配置方法,将调用(子)类作为参数。然后,该方法将确定类的类型,遍历继承树(将每个父类类型推送到堆栈中),然后简单地连续运行每个配置方法。我认为这个基本原则可能被称为反思,但我不确定。 (编辑:即使不太确定,现在肯定把我的话之前读到它。)

在基类中的方法可能是静态的,但...

我相信这样的事情会是可能的,但我并不真正在加快PHP的速度。我“会做搜索的一点点,看看是否语法和代码允许这样做。我希望,不过,你可以使用这个想法。

这是我的想法可怕的伪代码形式。

<?php 

class A { 
    static function configure(class) { 
     //get qualified class name from argument 
     //get inheritance tree for qualified class name, push each tier into array 
     //loop: pop array, call configure method for each class in hierarchy 

     //this might possibly work? 
    } 
} 

class B extends A { 
    function configure() { 
     print("I am B::configure() and provide additional functionality.<br/>\n"); 
    } 
} 

class C extends B { 
    function configure() { 
     print("I am C::configure() and provide additional functionality.<br/>\n"); 
    } 
} 

$c = new C; 
A::configure($c); 

?> 

同样,我会看一看,看看是否在PHP中什么事情都可能支持这一理论在此期间,我可以用几个downvotes住

编辑:实际上,这可能不是必须是静态的,如只要方法名称在继承过程中不重叠,那实际上可能会更加优雅一些,因为对象可以通过调用master来找到自己的类名称和层次结构配置方法。

0

这个怎么样? (原谅我的PHP语法,如果它不完美)

<?php 
class MyBase { 
    private $_isChild = true; 

    public function __construct() 
     $this->_isChild = false; 
    } 

    public function behave() { 
     if $this->_isChild { 
      parent::behave(); 
     } 
     self::doBehave(); 
    } 

    protected function doBehave() 
     // do stuff here! 
    } 
} 
?> 

在你的子类中,只实现doBehave。

最大

+0

今天早上测试了这一点。看起来我的代码不好。抱歉! – maxenglander

相关问题