/* +---------------------------------------------- --- ---------------------------------+ | = この記事は Haohappy によって読まれています> = 章のクラスand Objects Notes | = 翻訳 + 個人的な経験 | = 不必要なトラブルを避けるため、転載はご遠慮ください。 = 批判や修正は歓迎です。PHP 愛好家の皆さんと一緒に進歩していきたいと思っています。 -------------------------------------------------- -- --------------------+ */ セクション 15 -- Zend エンジンの開発 この章の最後のセクションでは、Zeev が Zend によってもたらされたオブジェクト モデルについて説明します。 1997 年の夏に PHP 3 を開発したとき、PHP をオブジェクト指向にするという計画はありませんでした。純粋にプロセス指向の言語ですが、1997 年 8 月 27 日の夜にクラスのサポートが PHP3 アルファ バージョンに追加されました。当時、PHP を検討していた人もいたため、PHP に新機能を追加するには最小限の議論しか必要ありませんでした。実際、この設計には関連するアイデアやオブジェクトのサポートがほとんどなかったため、PHP は 1997 年 8 月からオブジェクト指向プログラミング言語への第一歩を踏み出しました。このバージョンは、$foo["bar"] を使用する代わりに、より見栄えの良い $foo->bar を使用できる、配列にアクセスする優れた方法です。オブジェクト指向のアプローチの主な利点は、保存できることです。例 6.18 に、メンバー関数またはメソッドを使用した機能の例を示します。ただし、例 6.19 のアプローチとそれほど違いはありません。 $obj = new Example(); $obj->PrintValue(); ?> リスト 6.19 PHP 3 の構造プログラミング PHP3 の構造プログラミング 上記では、クラスに 2 行のコードを記述するか、配列を関数に明示的に渡します。ただし、PHP3 ではこれら 2 つのオプションに違いがないことを考えると、オブジェクト モデルを「構文のホワイトウォッシュ」としてのみ使用して配列にアクセスすることはできます。 オブジェクト指向開発に PHP を使用したい人、デザイン パターンを使用したい人、特にデザイン パターンを使用したいと考えていた人は、すぐに壁にぶつかりました。幸いなことに、当時 (PHP3 時代) はオブジェクト指向開発に PHP を使用したいと考えていた人は多くありませんでした。新しいバージョンでは、この状況が変わりました。これは、例 6.20 のように、PHP の異なる識別子がメモリ内の同じアドレスを指すようにすることができます。つまり、リスト 6.20 PHP 4 の参照 PHP4 での参照 以降。相互に参照するオブジェクトのネットワークを構築することはすべてのオブジェクト指向設計パターンの基礎ですが、この改善は非常に重要な意味を持ちますが、参照によってオブジェクトを他のオブジェクトと同じように扱うという PHP のアプローチが可能になります。 PHP4 プログラマーなら誰でも言うように、アプリケーションは WTMA (アンパサンドが多すぎる) 症候群に悩まされることになります。実際のアプリケーションを構築したい場合は、例 6.21 を見てください。リスト 6.21 PHP のオブジェクトの問題 4 PHP4 のオブジェクトの問題 1 class MyFoo { 2 function MyFoo() 3 { 4 $this ->me = &$this; 5 $this->value = 5; 7 8 関数 setValue($val) 9 { 10 $this->value = $val; 11 } 12 13 関数 getValue() 14 { 15 戻り $this->value 16 } 17 18 関数 getValueFromMe() 19 { 20 戻り $ this->me->value; 21 } 22 } 23 24 関数 CreateObject($class_type) 25 { 26 スイッチ ($class_type) { 27 ケース "foo": 28 $obj = new MyFoo(); 30 ケース "バー": 31 $obj = new MyBar(); 32 ブレーク; 33 } 34 return $obj; 35 }36 37 $global_obj = CreateObject ("foo"); 38 $global_obj->setValue(7); 39 40 print "値は " です。 global_obj->getValueFromMe() . "n"; まず、コンストラクター内で $this->me に参照を与え、他の 3 つのメンバー関数を設定します。 1 つは this->value の値を設定し、もう 1 つは this->value->me の値を返します。しかし、 --$this は同じものではないでしょうか。 () これは MyFoo::getValueFromMe() によって返される値と同じではありませんか? まず、MyFoo 型のオブジェクトを返す CreateObject("foo") を呼び出します。次に、MyFoo::setValue(7) を呼び出します。最後に、MyFoo::getValue() と MyFoo::getValueFromMe() を呼び出し、戻り値 7 を期待します。 もちろん、すべてのケースで 7 が得られたとしても、上記の例は本書の中で最も意味のない例というわけではありません。だから私はあなたを信じています すでに推測しています - 7 が 2 つも得られません。しかし、さらに重要なのは、得られる結果は 7 と 5 です。理由については、まず 3 つです。コンストラクターを見てください。コンストラクター内では、this と this->me の間の参照が確立されます。しかし、コンストラクターが終了すると、コンストラクター内になります。 PHP はオブジェクト (new MyFoo の 28 行目の結果) を再作成し、それを $obj に割り当てる必要があります。オブジェクトは他のデータ型と同様に特別に扱われないため、X を Y に割り当てることは、Y が X であることを意味します。つまり、obj は new MyFoo のコピーになり、new MyFoo はコンストラクター内に存在するオブジェクトになります。Obj->me は参照であるため、変更されていないオブジェクトを指します。出来上がり。obj と obj->me はもはや同じものではありません。これが最初の理由です。奇跡的に、オブジェクトのインスタンス化の問題を克服するつもりです。 28) CreateObject によって返された値を global_object に代入しても、やはり同じ問題に遭遇します。global_object は戻り値のコピーになり、やはり global_object と global_object ->me は同じではなくなります。 2 つ目ですが、実際にはまだそこまではできません。CreateObject が $obj を返したら、参照を破棄します (34 行目)。では、これを修正するにはどうすればよいでしょうか。 1 つは、例 6.22 (行 24、28、31、37) のように、あらゆる場所にアンパサンドを追加することです。 2. 幸運にも PHP5 を使用できる場合は、上記のすべてを忘れても構いません。PHP5 が自動的にこれを処理します。 PHP5 がこれをどのように考慮しているかを知りたい場合は、リスト 6.22 PHP 4 の WTMA シンドローム PHP4 の WTMA シンドローム 1 class MyFoo { 2 function MyFoo () 3 { 4 $this->me = &$this; this->value = 2; 6 } 7 8 関数 setValue($val) 9 { 10 $this->value = $val; 12 13 関数 getValue() 14 { 15 $this->value; 17 18 関数 getValueFromMe() 19 { 20 return $this->me->value; 21 } 22 }; 23 24 関数 &CreateObject($class_type) 25 { 26 スイッチ ($class_type) { 27 case "foo": 28 $obj = & new MyFoo(); 29 ブレーク; 30 ケース "バー": 31 $obj =& new MyBar(); 34 return $ obj;36 37 $global_obj =& CreateObject ("foo"); 38 $global_obj->setValue(7); 39 40 print "値は " です。 $global_obj->getValue() "; $global_obj->getValueFromMe() . "n"; PHP5 は、オブジェクトを他のタイプのデータとは異なるものとして扱う最初の PHP バージョンです。PHP5 では、オブジェクトは常に によって渡されます。他のタイプのデータ (整数、文字列、配列など) は値によって渡されますが、最も注目すべき点は、オブジェクト指向プログラミングではオブジェクトのネットワークを広く利用していることです。オブジェクト間の複雑な関係には参照を使用する必要がありました。以前のバージョンの PHP では、参照を明示的に指定する必要がありました。そのため、オブジェクトはデフォルトで参照によって移動され、明示的に要求された場合にのみコピーされるようになりました。 PHP5 より前では、すべての値は zval (Zend Value) と呼ばれる特別な構造体に格納されていました。これらの値は、数値や文字列などの単純な値、または複雑な値に格納できました。配列やオブジェクトなどの値が関数に渡されるとき、または関数から返されるとき、これらの値はコピーされ、同じ内容の構造体がメモリ内の別のアドレスに作成されます。 zvalとして オブジェクトを除くオブジェクトはオブジェクトストアと呼ばれる構造体に存在し、オブジェクトごとに異なるIDを持ちます。Zvalではオブジェクトそのものは格納されませんが、オブジェクトをコピーする際にはそのオブジェクトのポインタが格納されます。たとえば、オブジェクトの zval 構造を保持する場合、オブジェクトをパラメータとして関数に渡す場合、データはコピーされなくなり、同じオブジェクト ポインタを保持し、この特定のオブジェクトが現在別の zval によってポイントされていることをオブジェクト ストアに通知します。オブジェクト自体はオブジェクト ストアに配置されているため、オブジェクトに加えた変更は、そのオブジェクトへのポインタを保持するすべての zval 構造に影響します。この追加の間接化により、PHP オブジェクトが常に透過的かつ効率的な方法で参照によって渡されているかのように見えます。 PHP5 を使用して、例 6.21 に戻ってすべてのアンパサンドを削除すると、コンストラクター (4 行目) で参照を保持するときに、アンパサンドが 1 つも使用されません。
http://www.bkjia.com/PHPjc/532149.html