简体   繁体   English

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

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

I am working on a very simple template engine that would allow others to extend the template parsing functionality via subclassing the TemplateParser class. 我正在开发一个非常简单的模板引擎,允许其他人通过子类化TemplateParser类来扩展模板解析功能。 The skeleton of my TemplateParser class looks like this: 我的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;
            }
        }
    }

}

What I would like to do is be able to take a child class and add any number of replace_XXXXX methods in the child class that the parent "automatically" knows about. 我想做的是能够获取子类并在父类“自动”知道的子类中添加任意数量的replace_XXXXX方法。 My problem is that the __CLASS__ constant is always equal to 'TemplateParser', even when called on a child class. 我的问题是__CLASS__常量总是等于'TemplateParser',即使在子类上调用时也是如此。 Is there any way that I can get the methods of the child class from within TemplateParser? 有什么方法可以从TemplateParser中获取类的方法吗?

If you're going to use a static method why even bother asking users to extend the parent class? 如果您打算使用static方法,为什么还要求用户扩展父类呢?

OOP vs. COP OOP与COP

First, what you're suggesting is not OOP -- it's COP (Class Oriented Programming). 首先,你所建议的不是OOP - 它是COP (面向类的编程)。 I'd advise you to consider exactly why you've made TemplateParser::parse_template static in the first place. 我建议你先考虑一下你为什么 TemplateParser::parse_template静态。 Is there a really, really good reason ( hint : not likely)? 是否有一个非常非常好的理由( 提示 :不太可能)? Just because PHP 5.3 introduced late-static binding doesn't mean you should use it willy-nilly all over the place. 仅仅因为PHP 5.3引入了后期静态绑定并不意味着你应该在所有地方使用它。 In fact, static is rarely the best option . 事实上, static很少是最好的选择

Composition Over Inheritance 继承的组合

Second, your stated use-case doesn't provide any compelling reason for using inheritance. 其次,您声明的用例并未提供使用继承的任何令人信服的理由。 You should almost always favor composition over inheritance. 你应该几乎总是喜欢组合而不是继承。 Consider: 考虑:

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);
        }
    }
}

In the above code we're able to reap all the advantages of Dependency Injection wiki and our code is imminently more testable, maintainable and less prone to breakage than had we used a convoluted class-oriented implementation with static . 在上面的代码中,我们能够获得依赖注入wiki的所有优点,并且我们的代码显然比我们使用带有static的复杂的面向类的实现更易测试,可维护且不易破损。

Late static binding made this possible since php 5.3 with the builtin functions: get_called_class() and/or forward_static_call(). 由于带有内置函数的php 5.3,后期静态绑定使这成为可能:get_called_class()和/或forward_static_call()。 http://php.net/manual/en/language.oop5.late-static-bindings.php http://php.net/manual/en/language.oop5.late-static-bindings.php

Quick example: 快速举例:

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();

This outputs: child_class child_class 这输出:child_class child_class

Using the newly found class name keep the same logic you had in mind with get_class_methods(). 使用新发现的类名保持与get_class_methods()相同的逻辑。

Cheers 干杯

Try this: 试试这个:

// 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;
         }
      }
   }
}

I just wrote that up (with a little referencing of PHP documentation) but haven't tested it. 我刚刚写了这篇文章(稍微引用了PHP文档),但还没有测试过。 I'm sure you can make it do what you need it to do. 我相信你可以做它你需要它做的事情。

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

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