1

私は最近、オブジェクト指向の方法でphp5で開発を始めましたが、何かに行き詰まっています。私は本当にあなたの助け/推薦に感謝します。

それが混乱に終わったので、これで私と一緒に耐えてください:-(

これが私のシナリオです(これについて明確に説明できることを願っています):Vocabularyと呼ばれる静的クラスのメソッドを使用するClientとSupplierの2つの動的クラスがあります。語彙は、プレーンテキストファイル、mongodbデータベース、またはmysqlデータベースなどのソースから語彙用語を取得するクラスです。構成ファイルのエントリは、アプリケーションが前述の3つのタイプのソースのどれを使用するかを決定します。

class Client {
    public function foo() {
        ...
        Vocabulary::getTerm();
        ...
    }
    ...
}

class Supplier {
    public function bar() {
        ...
        Vocabulary::getTerm();
        ...
    }
    ...
}

class Vocabulary {
    public static function useVocab($vocab) {
        $_SESSION['vocab'] = $vocab;
    }
    public static function getTerm($termKey) {...}
    ...
}

サポートしたいタイプごとにVocabulary子クラスを作成することを計画しました。たとえば、Vocabulary_file、Vocabulary_mongodb、Vocabulary_mysqlなどです。Vocabulary_fileは、$ _ SESSION変数の設定から追加の操作appartを実行する必要があるため、親のuseVocab()をオーバーライドしますが、Vocabulary_mongodbとVocabulary_mysqlは、useVocab()の親メソッドをオーバーライドする必要はありません($ _SESSION変数セットが必要です)。3つの語彙の「子」クラスはすべてgetTerm()メソッドをオーバーライドします。

以下は私が試したものであり、これは私が最終的に得た混乱です:-(

  • Vocabulary_mongodbおよびVocabulary_mysqlの場合、useVocab()は存在しないが、Vocabularyから継承されているため、「method_exists()」はtrueを返し、その呼び出しによって無限ループが発生します。
  • Vocabularyで子を明示的に呼び出すことと、子クラスでparent::を呼び出すことの両方が奇妙に見えます。

たくさんのコーヒーを飲んだ後、私はすべての知恵を使い果たし、私の脳は損傷を受けました。

// Class Vocabulary modified to make it call the desired "child" class too
class Vocabulary {
    // This would execute "child" class method
    private static function _callChild($method, $args) {
        $child_class = 'Vocabulary_' . Config::$vocab['type']; // Config::$vocab['type']     can be: file, mongodb or mysql
        if (method_exists($child_class, $method)) {
            return call_user_func_array($child_class . '::' . $method, $args);
        } else {
            return false;
        }
    }
    public static function useVocab($vocab) {
        $_SESSION['vocab'] = $vocab;
        self::_callChild(__FUNCTION__, compact('vocab'));
    }
    public static function getTerm($termKey) {
        $termKey = strtolower($termKey);
        self::_callChild(__FUNCTION__, compact('termKey'));
    }
    ...
}

class Vocabulary_file extends Vocabulary {
    public static function useVocab($vocab) {
        parent::useVocab($vocab);
        // some specific stuff here
    }
    public static function getTerm($termKey) {
        parent::getTerm($termKey);
        // some specific stuff here
    }
}

class Vocabulary_mongodb extends Vocabulary {
    public static function getTerm($termKey) {
        parent::getTerm($termKey);
        // some specific stuff here
    }
}

class Vocabulary_mysql extends Vocabulary {
    public static function getTerm($termKey) {
            parent::getTerm($termKey);
        // some specific stuff here
    }
}

ClientやSupplierでの呼び出しのように、Vocabulary :: ...を維持するために、Vocabularyクラスを設計する方法を知りたいのですが、Vocabularyに「Config」クラスで構成されたタイプに使用する子クラスを知らせます。

アドバイスをいただければ幸いです。乾杯

4

2 に答える 2

0

キーワードselfは「late-static-binding」を処理できないという問題があります。基本的に、親クラスでselfは、それ自体の静的関数内にある場合、それは親クラスであると見なします(これselfは、レガシーの理由でコンパイル時に評価されるためです)。

static親クラスの代わりに使用する必要がありselfます(php 5.3以降を使用している場合)。

ところで:とにかくコンパイル時に知っている必要があるので、parentキーワードはあなたが期待するように機能します。parent

次に例を示します。

public static function getTerm($termKey) {
    $termKey = strtolower($termKey);
    static::_callChild(__FUNCTION__, compact('termKey'));
}

php 5.2以前を使用している場合は、すべての子クラスにクラス名を返す静的関数を要求するなど、ハックを試す必要があります。php5.3以降を使用していることを願っています...

于 2012-10-29T15:52:47.133 に答える
0

すべてのstaticメソッドを使用している場合は、OOPをまったく使用しない方がよいでしょう。基本的には、すべてグローバル関数呼び出しです。ポリモーフィズムによる継承を機能させたい場合は、クラスをインスタンス化する必要があります。ポリモーフィズムは、インスタンス化されたオブジェクトは何でもかまいませんが、それらに対して同じメソッドを呼び出しているという事実に由来します。例えば:

abstract class Vocabulary {

    abstract public function getTerm($termKey);

}

class Vocabulary_File extends Vocabulary {

    public function getTerm($termKey) {
        // get from file
    }

}

class Vocabulary_MySQL extends Vocabulary {

    public function getTerm($termKey) {
        // get from database
    }

}

このポリモーフィックは次のように使用できます。

if (mt_rand(0, 1)) {
    $vocab = new Vocabulary_File;
} else {
    $vocab = new Vocabulary_MySQL;
}

// This call is polymorphic.
//  What exactly it does depends on which class was instantiated.
$vocab->getTerm('foo');

これが、ポリモーフィズムが本当に役立つ方法です。インターフェイス(getTerm($termKey))は定義されており、クラス間で変更されていませんが、特定の実装は変更されています。コードがへの呼び出しをハードコーディングしている場合Vocabulary::getTerm()、それはポリモーフィズムではありません。あなたの構造では、重要なオブジェクト指向デザインルールにも違反しています。親はその子について知らず、その子と相互作用しません。子は親の機能をオーバーライドしますが、その逆ではありません。

$_SESSIONまた、をグローバルストレージの形式として使用しないでください。オブジェクトを自己完結型に保ちます。

于 2012-10-29T16:01:36.717 に答える