[PHP-users 10601] Re: 1つのインスタンスを参照する2つの変数のチェック方法

WADA Masashi php-users@php.gr.jp
Mon, 07 Oct 2002 14:44:06 +0900


 和田です。

KUROSAWA Akira wrote:
>1つのインスタンスを参照する2つの変数(リファレンス)がある場合に
>この2つの変数が同じインスタンスを参照している事を確認する方法
>を探しています。
>
>例えば下記の「check_ref」のような関数を作りたいのです。
>
><?php
>class Hoge
>{
>    var $hoge = 'abc';
>}
>
>$object1 =& new Hoge;
>$object2 =& new Hoge;
>
>$object1_ref =& $object1;
>
>if (check_ref($object1, $object2)) {
>    // ここは実行されません
>}
>
>if (check_ref($object1, $object1_ref)) {
>    // ここは実行されます
>}
>?>

 石を投げられそうな思いつきですが・・・。

----------------------------------------
<?php

class _Object
{
    var $_object_id;
    function _Object() {
        $this->_object_id = uniqid("", TRUE);
    }
    function is_equals($obj) {
        return ($this->_object_id == $obj->_object_id);
    }
}

class Hoge extends _Object
{
    var $hoge = 'abc';
}

$object1 =& new Hoge;
$object2 =& new Hoge;
$object1_ref =& $object1;

if ($object1->is_equals($object2)) {
    // ここは実行されません
}
if ($object1->is_equals($object1_ref)) {
    // ここは実行されます
}

?>
----------------------------------------

問題は uniqid() がどれだけユニーク性を保証してくれるのか、です。
(もしくは uniqid() の代わりに、自前でグローバルカウンタを用意す
るとか・・・。)


>PHPマニュアルの『第15章 リファレンスの説明』
>http://www.php.net/manual/ja/language.references.php
>
>のページで「check_reference」と言うそのものズバリのロジックが紹介されて
>いましたが、この方法を応用したとしても、引数として渡すオブジェクトに対し
>て次のような制限が発生してしまいます。

 上記のcheck_reference()は、なかなかトリッキーな解決策に見えま
した。言語仕様として判別方法が用意されていないのであれば、不本意
な解決策しか見つかりそうにないですね。

 しかしリファレンスかどうかを判定できたとしても、プログラマがソー
スコードを見て期待する本来のリファレンスかどうかは区別できないの
ではないでしょうか? というのは、PHP4が高速化のため次のような特
徴を持っているからです。

上記の check_reference() を利用した次のコードを実行してみると、

$a = 1;
$b = $a;
print "$a, $b : ".(check_reference($a, $b) ? "ref.\n" : "not ref.\n");
$a = 2;
print "$a, $b : ".(check_reference($a, $b) ? "ref.\n" : "not ref.\n");

結果は

1, 1 : ref.
2, 1 : not ref.

となります(テスト環境はPHP4.1.2/4.2.2)。

----
和田雅志 (WADA Masashi)
wada@hh.iij4u.or.jp