ホームページ >バックエンド開発 >PHPチュートリアル >Zendエンジンの開発[15]_PHPチュートリアル

Zendエンジンの開発[15]_PHPチュートリアル

WBOY
WBOYオリジナル
2016-07-21 16:10:54900ブラウズ


この章の最後のセクションでは、Zend Engine によってもたらされたオブジェクト モデルについて、特にそれが以前のバージョンの PHP のモデルとどのように異なるのかについて説明します
1997 年の夏に PHP3 を開発したとき、PHP を作成する計画はありませんでした。当時、PHP3 は純粋にプロセス指向の言語でしたが、1997 年 8 月 27 日の夕方にクラスのサポートが追加されました。 PHP には機能が与えられましたが、当時は PHP を研究する人があまりにも少なかったため、ほとんど議論する必要がありませんでした。そのため、1997 年 8 月から、PHP はオブジェクト指向プログラミング言語への第一歩を踏み出しました。

実際、これはこの設計には関連するアイデアがほとんどないため、このバージョンでのオブジェクトの使用は、配列にアクセスするための優れた方法に過ぎません。 ]、より見栄えの良い $foo->bar を使用できます。オブジェクト指向アプローチの主な利点は、メンバー関数またはメソッドを通じて機能を格納することです。ただし、例 6.19 とは異なります。実際、アプローチはそれほど変わりません。

リスト 6.18 PHP 3 のオブジェクト指向プログラミング PHP3 のオブジェクト指向プログラミング
クラスの例
{
var $value = "何らかの値";
function PrintValue()
{
print $this->value;
}
$obj = new Example(); obj->PrintValue();
?> リスト 6.19 PHP 3 の構造化プログラミング PHP3 の構造化プログラミング
function PrintValue($arr)
{
print $arr["value"]
}

function CreateExample()
{
$arr["value"] = "値"; ["PrintValue"] = "PrintValue";

return $arr = CreateExample(); //PHP の間接参照を使用します
$arr["PrintValue"]($arr); > 上記では、クラスに 2 行のコードを記述するか、関数に配列を明示的に渡していますが、PHP3 ではこれら 2 つのオプションに違いがないことを考慮すると、オブジェクト モデルを単に「構文上の光沢」として扱うことができます。

オブジェクト指向開発に PHP を使用したいと考えていた人、特にデザイン パターンを使用したいと考えていた人は、幸いなことに、当時 (PHP3 時代) は多くの人がそれを望んでいなかったことにすぐに気づきました。

PHP をオブジェクト指向開発に使用することで、この状況が変わります。これにより、PHP の異なる識別子がメモリ内の同じアドレスを指すことができるようになります。例 6.20 のように、同じ変数に名前を付けます。

リスト 6.20 PHP 4 の参照 PHP4 の参照
$a = 5;

//$b は $a と同じメモリの場所を指し、$a はメモリ内の同じアドレスを指します
$b = &$a// $a が Change $b を指しているので、$b を変更します
//同じ場所 - それも変わります $a が指すアドレスも変わります
$b = 7; /prints 7 Output 7
print $a;
?> 相互にポイントするオブジェクトのネットワークを構築することがすべてのオブジェクト指向設計パターンの基礎であるため、この改善は非常に重要です。強力なオブジェクト指向アプリケーションでは、PHP はオブジェクトを他の種類のデータと同じように扱うと、開発者に大きな苦痛を与えます。PHP4 プログラマーなら誰でも言うように、アプリケーションを構築しようとすると、WTMA (Way Too Many Ampersands) 症候群に悩まされることになります。実際のアプリケーションでは、非常に苦痛に感じるでしょう。例 6.21 を見れば理解できるでしょう。

リスト 6.21 PHP 4 のオブジェクトに関する問題 PHP4 でのオブジェクトの使用に関する問題
1 クラス MyFoo {
2 関数 MyFoo()
3 {
4 $this->me = &$this;
5 $this->value = 5
6 }
7
8 関数 setValue($val)
9 {
10 $this->value = $val;
11 }
12
13 関数 getValue()
14 {
15 $this->value を返す
16 }
17
18 関数 getValueFromMe()
19 {
20 return $this->me->value;
21 }
22 }
23
24 function CreateObject($class_type)
25 {
26 switch ($class_type) {
27 case "foo" :
28 $obj = new MyFoo();
30 ケース "bar":
31 $obj = new MyBar();
34 return $obj;
36
37 $global_obj = CreateObject ("foo");
38 $global_obj->setValue(7);
39
40 print "値は " です。 41 print "値は " です。 $global_obj->getValueFromMe() "; まず、MyFoo クラスがあり、コンストラクターで $this->me に参照を与え、 set
他の 3 つのメンバー関数があります。1 つは this->value の値を設定します。 1 つは this->value の値を返し、もう 1 つは this->value->me の値を返します。しかし、 --$this と MyFoo::getValueFromMe は同じものではないでしょうか。 () によって返される値は同じではありませんか?

まず、MyFoo 型のオブジェクトを返す CreateObject("foo") を呼び出します。次に、MyFoo::setValue(7) を呼び出します。 : getValue() と MyFoo::getValueFromMe() は、戻り値 7 を取得することを期待します。
もちろん、いずれにしても 7 を取得した場合、上記の例はこの本の中で最も無意味な例ではないでしょう。ご想像のとおり、7 が 2 つも得られません

しかし、どのような結果が得られるのでしょうか。さらに重要なのは、なぜ 7 と 5 が得られるのでしょうか。理由については、3 つあります

まず、コンストラクターを見てください。コンストラクター内では、this と this->me の間の参照が確立されます。しかし、コンストラクター内では、this と this->me は同じものになります。コンストラクターが終了すると、PHP はオブジェクト (new MyFoo の 28 行目の結果) を再作成し、それを $obj に割り当てる必要があります。オブジェクトは他のデータ型と同様に特別に扱われないため、X を Y に割り当てることは次のことを意味します。 Y はのコピーです。変更されずに、元のオブジェクトを指します。これは、もう同じものではありません。一方を変更しても、他方は変更されません

上記は次のとおりです。最初の理由は他にもあります。 最初の理由は、CreateObject によって返された値を global_object に代入すると、奇跡的に解決されます。 global_object はコピーの戻り値になり、global_object と global_object->me は同じではなくなります

しかし、実際には、CreateObject が $obj を返すまではまだそこまではいきません。これは 3 番目の理由です

では、これを修正するには 2 つのオプションがあります (例 6.22、24、28 行目)。 2. 幸運にも PHP5 を使用できる場合は、上記のことをすべて忘れても構いません。PHP5 がこれらの問題をどのように考慮するかを知りたい場合は、リスト 6.22 を読み続けてください。 PHP 4 の WTMA 症候群 PHP4 の WTMA 症候群 1 クラス MyFoo {
2 関数 MyFoo()
3 {
4 $this->me = &$this;
5 $this->value = 2
6 }
7
8 関数 setValue($val)
9 {
10 $this->value = $val;
11 }
12
13 関数 getValue()
14 {
15 $this->value を返す
16 }
17
18 関数 getValueFromMe()
19 {
20 return $this->me->value;
21 }
22 };
23
24 関数 &CreateObject($class_type)
25 {
26 switch ($class_type) {
27 case "foo ":
28 $obj =& new MyFoo();
29 Break;
30 case "bar":
31 $obj =& new MyBar();
32 Break;
33 }
34 return $obj;
35 }
36
37 $global_obj =& CreateObject ("foo");
38 $global_obj->setValue(7);
39
40 print "値は " です。
41 print "Value is " . $global_obj->getValueFromMe() . "n"; PHP5 は、オブジェクトを他のタイプのデータとは異なるものとして扱う最初の PHP バージョンであることがわかります。方法 - PHP5 では、オブジェクトは常に参照によって渡されますが、他のタイプのデータ (整数、文字列、配列など) は値によって渡されます。最も注目すべき点は、オブジェクトの参照による受け渡しを示すために & 記号を使用する必要がないことです。

オブジェクト指向プログラミングでは、オブジェクト ネットワークとオブジェクト間の複雑な関係が広範囲に使用されますが、そのすべてで参照を使用する必要がありました。そのため、以前のバージョンの PHP では、参照を明示的に指定する必要がありました。オブジェクトを移動し、明示的にコピーが要求された場合にのみオブジェクトをコピーします。これは以前よりも優れています。

PHP5 より前では、すべての値は zval (Zend Value) と呼ばれる特別な構造に格納されていました。数値や文字列などの単純な値、または配列やオブジェクトなどの複雑な値として格納できます。値が関数に渡されるとき、または関数から返されるときに、これらの値がコピーされ、別のアドレスにバンドが作成されます。

PHP5 では、オブジェクトを除いて値は zval 構造体に格納され、オブジェクトストアと呼ばれる構造体に存在します。Zval では、オブジェクトはそれぞれ異なる ID を持ちます。それ自体は保存されませんが、オブジェクトへのポインタを保持します。たとえば、オブジェクトをパラメータとして関数に渡す場合、同じオブジェクト ポインタを保持するだけです。 zval は、この特定のオブジェクトが現在指していることをオブジェクト ストアに通知します。オブジェクト自体はオブジェクト ストアにあるため、それに加えた変更は、そのオブジェクトへのポインタを保持するすべての zval 構造に影響します。間接指定により、PHP オブジェクトは常に透過的かつ効率的な方法で参照によって渡されるようです。

PHP5 では、例 6.21 に戻り、すべてのアンパサンドを削除しても、すべて正常に動作します。コンストラクター (4 行目) では、参照を保持するときにアンパサンドが使用されません。

http://www.bkjia.com/PHPjc/314111.html

tru​​ehttp://www.bkjia.com/PHPjc/314111.html技術記事この章の最後のセクションでは、Zend Engine によってもたらされたオブジェクト モデルについて、特に 1997 年の夏に PHP3 を開発したとき、それが以前のバージョンの PHP のモデルとどのように異なるのかについて説明します。
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。