私はOOPにかなり慣れておらず、1つのクラス名を使用するのに最適な方法について質問がありますが、渡されたパラメーターに基づいてそのクラスに機能を内部的に追加します。
基本的な話は、2つのパラメーター$moduleと$idを受け取る'item'クラスがあるということです。一部の「モジュール」(すべてではありません)には、「item」クラスにデフォルトで含まれない優れた機能があります。一部のモジュールでは、itemクラスの一部のメソッドも上書きする必要があります。私の目標は、itemクラスの__construct内から'item'クラスのモジュールの拡張機能を呼び出せるようにすることです。ただし、単一の「アイテム」クラスが必要です。
私の最初の考えは、アイテムクラスを構築するときにモジュールのアイテム拡張クラスのインスタンスを作成することです。次に、アイテムクラスのメソッドを呼び出すたびに、そのモジュール固有のインスタンスがあるかどうかを確認し、メソッドを呼び出します。そのインスタンスで。
例えば:
class item {
// Variable where I'll store the instance of the child class
var $child;
// Child class may call up item's constuct, I'll use this to avoid an infinite loop
var $child_initalized;
// Child called, guess we have to keep track of this so we don't get stuck in infite loops either.
var $child_called = 0;
// Example variables
var $id, $name;
function __construct($module,$id) {
if(!$this->child_initialized) {
$this->child_initialized = 1; // So we don't do this again and get stuck in an infite loop
$child_class = __CLASS__.'_'.$module;
if(class_exists($child_class)) {
$this->child = new $child_class($module,$id);
return;
}
}
// do normal class construction stuff here, such as setting $this->id and $this->name
$this->module = $module;
$this->id = $id;
}
// So we can catch child methods not in parent item class
function __call($name,$arguments) {
if($this->child) {
return $this->child->$name();
}
}
function id() {
$this->child_called = 0;
if($this->child) {
$this->child_called = 1;
return $this->child->id();
}
return $this->id;
}
}
class item_photos extends item {
function __construct($module,$id) {
$this->child_initialized = 1;
parent::__construct($module,$id);
}
function id() {
return "photo-".$this->id;
}
function photo_width() {
return 250; // Just some sample value
}
}
$item = new item('photos',123);
print $item->id()."<br />"; // photo-123
print $item->photo_width()."<br />"; // 250
とにかく、それはほんの簡単な例でした。しかし、私の方法は...まあ、間違っているようです。これを達成するためのより良い方法はありますか、それとも私がすべてをどのように構成しているかを再考する必要がありますか?あなたが提供できるアドバイスやアイデアは素晴らしいでしょう。
/ * ** * ** * ****編集**** ** * ** * * / _ _ _ _
明確にするために、私の目標は、実際には1つのクラス(私の例では「item」)を呼び出し、渡された1つ以上のパラメーターに基づいて、それらのパラメーターに基づいてより多くの機能を動的にロードできるようにすることです(私の例では、それは$ moduleです)。ただし、その追加機能が常に存在するとは限りません(したがって、new item()の代わりにnew item_photosを常に呼び出すことはできません)。
これが更新された例です。コードの最後で$item= new item('videos'、456)を呼び出すことは、一部のモジュールに追加機能がない方法の例です。
class item {
// Variable where I'll store the instance of the child class
public $child;
// Child class may call up item's constuct, I'll use this to avoid an infinite loop. Also to avoid when calling child class in methods.
public $child_initalized;
// Example variables
public $module, $id, $name;
function __construct($module,$id) {
if(!$this->child_initialized) {
$child_class = __CLASS__.'_'.$module;
if(class_exists($child_class)) {
$this->child = new $child_class($module,$id);
return;
}
}
// do normal class construction stuff here, such as setting $this->id and $this->name
$this->module = $module;
$this->id = $id;
}
// So we can catch child methods not in parent item class
function __call($name,$arguments) {
if($this->child) {
return $this->child->$name();
}
}
function id() {
$this->child_initalized = 0;
if($this->child) {
$this->child_initalized = 1;
return $this->child->id();
}
return $this->id;
}
}
class item_photos extends item {
function __construct($module,$id) {
$this->child_initialized = 1;
parent::__construct($module,$id);
}
function id() {
return "photo-".$this->id;
}
function photo_width() {
return 250; // Just some sample value
}
}
$item = new item('photos',123);
print "photo id: ".$item->id()."<br />"; // photo-123
print "photo size: ".$item->photo_width()."<br />"; // 250
$item = new item('videos',456);
print "video id: ".$item->id()."<br />"; // 456
print "video size: ".$item->photo_width()."<br />"; // nothing (that method doesn't exist here)
/ * ** * ** ****編集2 *** * ** * *** / _ _
まだ少し苦労しています。抽象ファクトリを調べましたが、機能しないようです。それらを正しく理解していれば、抽象クラスですべてのメソッドを宣言する必要があります。これは、モジュールがアイテムクラスを拡張するため、すべてのメソッドがわからないため、注意が必要です。さらに、避けようとしているのは「item」ではなく、「item_photos」または「item_videos」と呼ばなければならないようです。言うまでもなく、私の例ではitem_videosも存在しません。
1つのクラスを呼び出すという私の目標を考慮して、そのクラス__construct内で、$ moduleに基づいて含める必要のある追加機能があるかどうかを判断し、これを考え出しました。
基本的に、「item」クラスは新しい「item_core」に移動されます。古いアイテムクラスは、モジュールのアイテムクラス(例:item_photos)またはコアアイテムクラス(item_core)のいずれかを使用するクラスを決定するだけです。これらのクラスの1つを初期化した後、インスタンスを保存し、メソッドを呼び出すたびにそれを使用します(__callを介して、__ callを使用するのが悪い理由を教えてください)。
class item {
// Instance of the core class or module class
private $instance;
function __construct($module,$id) {
$class = __CLASS__;
$class_core = $class.'_core';
$class_module = $class.'_'.$module;
// Module class
if(class_exists($class_module)) $this->instance = new $class_module($module,$id);
// Core class
else $this->instance = new $class_core($module,$id);
}
// Catch all calls, redirect accordingly
function __call($name,$arguments) {
if($this->instance) {
if(method_exists($this->instance,$name)) return $this->instance->$name();
}
}
}
class item_core {
public $module, $id;
function __construct($module,$id) {
$this->module = $module;
$this->id = $id;
}
function id() {
return $this->id;
}
}
class item_photos extends item_core {
function __construct($module,$id) {
parent::__construct($module,$id);
}
function id() {
return "photo-".$this->id;
}
function photo_width() {
return 250; // Just some sample value
}
}
$item = new item('photos',123);
print "photo id: ".$item->id()."<br />"; // photo-123
print "photo size: ".$item->photo_width()."<br />"; // 250
$item = new item('videos',456);
print "video id: ".$item->id()."<br />"; // 456
print "video size: ".$item->photo_width()."<br />"; // nothing (that method doesn't exist in the videos module)
誰かがこれに問題があるか、とにかくそれを改善するために何かを見ますか?それはまだ私には少しずれているようです。
/ * ***編集3** * **** /
了解しました。私がやりたいことは、呼び出したものとは異なるインスタンスを返すことができるようにすることです。したがって、new item($ module、$ id);を呼び出しますが、$ module == photos(私の例では)の場合、new item_photos($ module、$ id);のインスタンスを返したいと思います。これまでのところ、2つの可能な解決策を考え出しました。
最初は、編集2で概説したものです(上記を参照)。
2番目のオプションは、関数(おそらく'item')を呼び出して、そこに正しいオブジェクトインスタンスを返すことです(関数は必要なオブジェクトインスタンスを返すことができますが、クラスコンストラクターは独自のクラスのインスタンスのみを返すため)。だから(基本的な例):
function item($module,$id) {
$class_module = 'item_'.$module;
// Module class
if(class_exists($class_module)) return new $class_module($module,$id);
// Core class
else return new item($module,$id);
}
class item{..}
class item_photos{..}
$item = item('photos',123);
print $item->id(); // photo-123
関数/クラスを混合するのが好きかどうかはわかりませんが、それは非常に簡単にトリックを実行します。
考え?