从PHP中的抽象父类访问子方法

时间:2012-05-09 23:30:46

标签: php oop inheritance

我正在开发一个非常简单的模板引擎,允许其他人通过子类化TemplateParser类来扩展模板解析功能。我的TemplateParser类的骨架如下所示:

abstract class TemplateParser {

    public static function parse_template($template_file) {
        //Do stuff with $template_file

        $specials = array();
        foreach (get_class_methods(__CLASS__) as $method) {
            if(strpos($method, "replace_") !== false) {
                $specials[] = $method;
            }
        }
    }

}

我想做的是能够获取子类并在父类“自动”知道的子类中添加任意数量的replace_XXXXX方法。我的问题是__CLASS__常量始终等于'TemplateParser',即使在子类上调用时也是如此。有什么办法可以从TemplateParser中获取 child 类的方法吗?

3 个答案:

答案 0 :(得分:4)

如果您打算使用static方法,为什么还要求用户扩展父类呢?

OOP与COP

首先,你所建议的不是 OOP - 它是 COP (面向类的编程)。我建议你首先考虑为什么你已经TemplateParser::parse_template静态了。是否有一个非常非常好的理由(暗示:不太可能)?仅仅因为PHP 5.3引入了后期静态绑定并不意味着你应该在所有地方使用它。实际上,static is rarely the best option

超过继承的组合

其次,您声明的用例并未提供使用继承的任何令人信服的理由。你应该几乎总是喜欢组合而不是继承。考虑:

interface ParserInterface
{
    public function parse_template($template_file);
}

interface ReplacerInterface
{
    // fill in your own interface requirements here
}

class Parser implements ParserInterface
{
    private $replacer;

    public function __construct(ReplacerInterface $replacer)
    {
        $this->replacer = $replacer;
    }

    public function parse_template($template_file)
    {
        $specials = array_filter(function($method) {
            return strpos($method, "replace_") === 0;
        }, get_class_methods($this->replacer));

        foreach ($specials as $method) {
            $this->replacer->$method($template_file);
        }
    }
}

在上面的代码中,我们能够获得Dependency Injectionwiki的所有优点,而且我们的代码显然比我们使用{{1的复杂的面向类的实现更容易测试,可维护且不易破损}}

答案 1 :(得分:1)

由于php 5.3具有内置函数:get_called_class()和/或forward_static_call(),所以后期静态绑定使这成为可能。 http://php.net/manual/en/language.oop5.late-static-bindings.php

快速举例:

class parent_class {
    public function method() {
        echo get_called_class(),PHP_EOL;
    }
    public static function smethod() {
        echo get_called_class(), PHP_EOL;
    }
}

class child_class extends parent_class {
}

$a = new child_class();
$a->method();
$a::smethod();

这输出: child_class child_class

使用新发现的类名与get_class_methods()保持相同的逻辑。

干杯

答案 2 :(得分:0)

试试这个:

// Array to hold special functions
$specials = array();

// Get all defined classes in script
$all_classes = get_declared_classes();    

// Loop through all classes
foreach($all_classes as $class)
{
   // Check if class is a child of TemplateParser
   if( is_subclass_of($class,'TemplateParser') )
   {
      // This class is a child of TemplateParser.
      // Get it's methods. 
      foreach (get_class_methods($class) as $method) 
      {
         if(strpos($method, "replace_") !== false) {
            $specials[] = $method;
         }
      }
   }
}

我刚刚编写了这篇文章(稍微引用了PHP文档)但尚未对其进行测试。我相信你可以做到你需要做的事情。