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

上記のコードでは、依存性注入wikiのすべての利点を享受することができ、コードは、複雑なクラス指向の実装を使用した場合よりも、すぐにテスト可能で、保守可能で、破損しにくくなっていstaticます。

于 2012-05-10T00:28:29.023 に答える
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()で念頭に置いていたのと同じロジックを使用してください。

乾杯

于 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 に答える