我正在开发一个非常简单的模板引擎,允许其他人通过子类化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 类的方法吗?
答案 0 :(得分:4)
如果您打算使用static
方法,为什么还要求用户扩展父类呢?
首先,你所建议的不是 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文档)但尚未对其进行测试。我相信你可以做到你需要做的事情。