PHP5 クラス:構成されたクラスを継承しますか?
-
13-09-2019 - |
質問
以下を動作させようとしていますが、途方に暮れています...
class Foo {
public $somethingelse;
function __construct() {
echo 'I am Foo';
}
function composition() {
$this->somethingelse =& new SomethingElse();
}
}
class Bar extends Foo {
function __construct() {
echo 'I am Bar, my parent is Foo';
}
}
class SomethingElse {
function __construct() {
echo 'I am some other class';
}
function test() {
echo 'I am a method in the SomethingElse class';
}
}
私がやりたいのは、Foo クラス内に SomethingElse クラスのインスタンスを作成することです。これは次を使用して機能します =&
. 。しかし、クラス Foo をクラス Bar で拡張すると、子は親クラスからすべてのデータ属性とメソッドを継承すると考えました。しかし、どうやら $this->somethingelse
子クラス Bar では機能しません:
$foo = new Foo(); // I am Foo
$foo->composition(); // I am some other class
$foo->somethingelse->test(); // I am a method in the SomethingElse class
$bar = new Bar(); // I am Bar, my parent is Foo
$bar->somethingelse->test(); // Fatal error: Call to a member function test() on a non-object
では、そのような形で継承することはできないのでしょうか?また、そこで使用したい場合は、クラス Bar 内からクラス SomethingElse の新しいインスタンスを作成する必要がありますか?それとも何かが足りないのでしょうか?
よろしくお願いいたします。
解決
子は親クラスからすべてのデータ属性とメソッドを継承すると考えていました。
これは当てはまります。子クラスは親クラスから静的変数と静的メソッドを継承します。さらに、子オブジェクトは静的変数とインスタンス変数およびメソッドを継承します。
既存のクラス構造で必要なものを取得する 1 つの可能性は次のとおりです。
$bar = new Bar();
$bar->composition();// here you are calling the parent method, sets instance var $somethineelse
$bar->somethingelse->test();// now you can call methods
子インスタンスで変数 (この場合はオブジェクト) を継承する別の方法は次のようになります。
class Foo {
protected $somethingelse;
public function __construct() {
$this->somethingelse = new SomethingElse();
}
}
class Bar extends Foo {
public function __construct() {
parent::__construct();
// now i've got $somethingelse
}
}
PHP 5 のクラスとオブジェクトの概要については、ここを参照してください。http://php.net/manual/en/ language.oop5.phpOO が初めての場合は、必ずすべて読んでください。おそらく 2 回ほど読んでください。
他のヒント
バーには、FOOから継承されsomethingelseという名前のメンバ変数を持っています。
は、オブジェクトとクラスのスコープを混合されています。
あなたが本当に説明した効果を達成する必要がある場合は、、あなたはあなたの変数、静的をしなければならないので、そのコンテキストが
クラスベースでありますまず、あなたは、静的およびインスタンス変数を区別する必要があります。静的変数は、クラスのすべてのインスタンス間で共有され、インスタンス変数ではありません。
あなたはfooとbarのすべてのインスタンスはまったく同じSomethingElseインスタンスを持っているしたい場合は、$ somethingelse静的を行う必要があります:
のpublic static $ somethingelse
あなたがfooの構成機能を変更する必要があります:
function composition() {
self::$somethingelse = new SomethingElse();
}
あなたは次の操作を行うことができ、この静的フィールドにアクセスするには: $ fooという=新しいはFoo(); //私はFooのです $ foo->構図(); //私はいくつかの他のクラスです フー:$ somethingelse->テスト(); //私はSomethingElseクラスのメソッドだ。
$バー=新しいバー(); //私はバーだ、私の親はFooのです バー:: $ somethingelse->テスト(); //私はSomethingElseクラスのメソッドだ。
あなたがしたい場合は、fooとbarのすべてのインスタンスは、あなたがあなたのコードを使用することができ、自分のSomethingElseインスタンスを持っていますが、
を追加する必要があります$バー - >構成()
の前に$バー - > somethingelse->テスト();
これが原因であります。
$バー=新しいバー();
あなたはバーの完全に新しいインスタンスを作成し、そのインスタンスは$ somethingelse性質を持っていますが、それはまだ設定されていません。だから、それを設定する)(組成を呼び出す必要があります。
すべてのfooとbarがまったく同じSomethingElseインスタンスを持っている必要がある場合は、それが必要なメモリを減少させるので、、あなたは、代わりに静的なバージョンを使用する必要があります。
私は、これはあなたを助けることができると思います。そうでなければ私はさらにそれを説明するのは非常に満足しています。
クラスが属性を共有すると言っても、オブジェクトが共有するという意味ではありません 属性値.
他の人が指摘したように、クラスとインスタンスを混同しています。
次の場合も同じエラーが発生することに注意してください。
$foo = new Foo(); // I am Foo
$foo->composition(); // I am some other class
$foo->somethingelse->test(); // I am a method in the SomethingElse class
$foo2 = new Foo(); // I another Foo
$foo2->somethingelse->test(); // Fatal error: Call to a member function test() on a non-object
クラスをあまり抽象的に考えないでください。たとえば、「Royalty」の親クラスである「person」クラスがあるとします。
次に、次のようにした場合:
$me = 新しい人();$me->firstName = "トーマス"
$princeCharles = 新しいロイヤリティ();
$princeCharles に "Thomas" と等しい firstName 属性を持たせることは望ましくありません。また、$princeCharles->firstName を設定したい場合は、$me の firstName 属性の値を変更する必要はありません。
$me と $princeCharles はどちらも属性 'firstName' を持っていますが、属性を共有しません。 価値 その属性の。
私は、派生クラスのコンストラクタで親クラスのコンストラクタを呼び出します場合は、あなたの問題が解決されると思います。これは、あなたがデータメンバを継承して問題を持っているときに念頭に置いてそれを維持するPHPにデフォルトで発生しません。
クラスバーはFooを{延び パブリック関数__construct(){ 親:: __構築物();
}
}