繁体   English   中英

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

[英]Accessing a child's methods from abstract parent class in PHP

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

如果您打算使用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);
        }
    }
}

在上面的代码中,我们能够获得依赖注入wiki的所有优点,并且我们的代码显然比我们使用带有static的复杂的面向类的实现更易测试,可维护且不易破损。

由于带有内置函数的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()相同的逻辑。

干杯

试试这个:

// 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文档),但还没有测试过。 我相信你可以做它你需要它做的事情。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM