3

我正在开发一个非常简单的模板引擎,它允许其他人通过继承 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中获取子类的方法?

4

3 回答 3

4

如果您要使用一种static方法,为什么还要麻烦用户扩展父类?

OOP 与 COP

首先,您所建议的不是OOP——而是COP(面向类的编程)。我建议您首先考虑一下为什么TemplateParser::parse_template设置静态。是否有一个非常非常好的理由(提示:不太可能)?仅仅因为 PHP 5.3 引入了后期静态绑定并不意味着您应该在所有地方都随意使用它。事实上,static很少是最好的选择

组合优于继承

其次,您陈述的用例没有为使用继承提供任何令人信服的理由。您几乎应该总是倾向于组合而不是继承。考虑:

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 Injection wiki的所有优势,并且与使用static.

于 2012-05-10T00:28:29.023 回答
1

后期静态绑定使这成为可能,因为 php 5.3 具有内置函数:get_call_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() 相同的逻辑。

干杯

于 2012-05-10T00:03:51.020 回答
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 文档),但还没有测试过。我相信你可以让它做你需要它做的事情。

于 2012-05-09T23:40:22.967 回答