2015-10-07 15 views
6

私は大量のPHPクラス関数を即座にインポートする方法を理解しようとしています。たとえば...オンザフライでPHPクラス関数を再定義しますか?

class Entity 
{ 
    public function __construct($type) 
    { 
    require_once $type."_functions.php" 
    } 

    // ... 

} 

$person = new Entity("human"); 
$person->sayhi(); 
$cow = new Entity("cow"); 
$cow->sayhi(); 

human_functions.php:

class Entity redefines Entity 
    { 
    public function sayhi() 
     { 
     echo "Hello world!"; 
     } 
    } 

cow_functions.php:

class Entity redefines Entity 
    { 
    public function sayhi() 
     { 
     echo "Moo!"; 
     } 
    } 

私は "実験" ですclasskit_method_redefine()runkit_method_redefine()のようないくつかの可能性を(発見しましたとにかく現在実行中のクラスを変更することはできません)。私はPHP 5.3.3を使用していますので、Traitsを使用することはできません(これは私がとにかく探しているものか分かりません)。

// Example 2: 
class OtherEntity { /* Code Here */ } 
class Entity 
    { 
    public function __construct($type) 
     { 
     global $foo; 
     unset($foo); 
     $foo = new OtherEntity(); 
     } 
    } 

$foo = new Entity(); 

しかし、これは非常にハック方法のように感じている:私ははこのようなハンドラの変数を再定義し成功を収めている。さらに重要なことに、私がという名前をのすべてのインスタンスに指定しないと、動作しません。私がやろうとしていることに対する回避策はありますか?

注:私はクラスを拡張することができますが、私の場合、Entityクラスが開始されたときに、どのサブクラスを開始する必要があるかを事前に知る安全な方法はありません。おそらく、以下のような書き方があります。

public function changeClass 
    { 
    this->class = OtherEntity; 
    } 

ありがとうございます!

+2

あなたの実際の問題に対する別の解決策があります。あなたの最初の例は[工場パターン](http://www.tutorialspoint.com/design_pattern/factory_pattern.htm)を提案していますが、あなたが本当に達成したいことについてはわかりません。 – VolkerK

+2

あなたは考え直す必要があるいくつかのデザインの選択肢を作った。 –

+0

は実際のphp関数を '再定義する '。私はあなたが '拡張'を探していると信じています – CodeGodie

答えて

5

ここでは、試してみる可能性のある解決策について考えています。 CowおよびHumanクラスをEntityクラスに拡張します。ただし、Entityクラスは、値が安全である場合に基づいてオブジェクトをインスタンス化するためにfactoryを使用します。のは、より詳細に本を見てみましょう:

/* 
* Class Entity should not be able to be instantiated. 
* It should contain a factory to instantiate the 
* appropriate entity and an abstract function declaring 
* the method that each entity will need to implement. 
*/ 
abstract class Entity { 

    public static function factory($type) { 
     return (is_subclass_of($type, "Entity")) ? new $type() : FALSE; 
    } 

    abstract public function sayHi(); 

} 

/* 
* Human class extends Entity and implements the 
* abstract method from Entity. 
*/ 
class Human extends Entity { 

    public function sayHi() { 
     echo "Hello World!"; 
    } 

} 

/* 
* Cow class extends Entity and implements the 
* abstract method from Entity. 
*/ 
class Cow extends Entity { 

    public function sayHi() { 
     echo "Moo!"; 
    } 

} 

さて、このメソッドを使用するファクトリメソッドを呼び出し、すべてがうまく動作するかどうか、それはEntityを延長する適切なクラスをインスタンス化しますし。

$person = Entity::factory("Human"); 
$person->sayHi(); 

$cow = Entity::factory("Cow"); 
$cow->sayHi(); 

使用して、is_subclass_of()が安全を維持します値に渡された場合はEntityを拡張するクラスではないので、あなたはFALSEの値が返されます。

上記のコードを実際に使用したい場合は、上記のPHPコードをコピーしてphpfiddle.orgにテストしてください。

+0

あなたは男です。ありがとうございました!これはまさに私が探していたものです。 なぜ '' 'sayHi();' '関数を抽象的に定義していますか?元の '' Entity''クラスで定義されていなくても動作しているようです。 – DarthCaniac

+2

@DarthCaniac正しいです。それは絶対にあります。 'abstract'キーワードの利点は、'抽象関数 'を使って基本クラスを拡張しているクラスが、そのクラス内でそのメソッドを実装するよう強制します。つまり、 'Human'と' Cow'の両方が 'sayHi()'を実装する必要があります。そうしないと、PHPインタプリタがエラーを投げます。これは、 'Entity'を拡張するクラスには、そのクラスに固有の何かを行うことができる有効な' sayHi() 'メソッドが含まれていることを保証します。 – War10ck

+0

@ noc2spamツ詳細を教えてください。何かのようにしないでください... – War10ck

1

あなたができることの1つは、EntityのサブクラスとしてHumanCowを作成することです。 new Entity("Human")を実行すると、新しく作成したHumanオブジェクトEntityインスタンス内に保存できます。

次に、__callを使用して、メソッド呼び出しを「子要素」にリダイレクトできます。

class Entity{ 
    private $child; 

    public function __construct($type){ 
     $this->child = new $type; 
    } 

    public function __call($func, $params=array()){ 
     $method = method_exists($this, $func) 
      ? [$this, $func] : [$this->child, $func]; 
     return call_user_func_array($method, $params); 
    } 
} 

class Human extends Entity{ 
    public function __construct(){} 

    public function sayhi(){ 
     echo "Hello world!"; 
    } 
} 

class Cow extends Entity{ 
    public function __construct(){} 

    public function sayhi(){  
     echo "Moo!"; 
    } 
} 

$person = new Entity("Human"); 
$person->sayhi(); 

$cow = new Entity("Cow"); 
$cow->sayhi(); 

唯一の欠点は$person$cowの両方Entityオブジェクトであるということです。

+1

さらなる読解:それは[オブジェクト構成](https://en.wikipedia.org/wiki/Object_composition)の1つの形式になります。 – VolkerK

+0

独創的なソリューション、ありがとう! – DarthCaniac

関連する問題