Forum und email

생성자의 재참조

생성자 내로 참조를 만드는 것은 혼란스런 결과를 유도할수 있다. 이런 튜토리얼같은 섹션이 문제를 회피하도록 도와준다.

<?php
class Foo
{
    function 
Foo($name)
    {
        
// 전역 배열 $globalref 안에 참조를 만든다
        
global $globalref;
        
$globalref[] = &$this;
        
// 값을 전달하기 위해 이름을 부여한다
        
$this->setName($name);
        
// 그리고 그것을 출력한다
        
$this->echoName();
    }

    function 
echoName()
    {
        echo 
"<br>",$this->name;
    }
 
    function 
setName($name)
    {
        
$this->name $name;
    }
}
?>

= 복사 연산자를 사용하여 만들어지는 $bar1=& 참조 연산자를 사용하여 만들어지는 $bar2 사이에 차이점이 있는지 확인해보자...

<?php
$bar1 
= new Foo('set in constructor');
$bar1->echoName();
$globalref[0]->echoName();

/* output:
set in constructor
set in constructor
set in constructor */

$bar2 =& new Foo('set in constructor');
$bar2->echoName();
$globalref[1]->echoName();

/* output:
set in constructor
set in constructor
set in constructor */
?>

외관상으로 둘 사이에는 아무 차이점도 없다. 그러나 실제로 매우 중요한 사실이 하나 있다: $bar1$globalref[0]은 참조되지 않는다. 그들은 같은 변수가 아니다. 이것은 "new"가 기본적으로 참조를 돌려주지 않기 때문이다. 대신 그것은 복사본을 돌려준다.

Note: 참조 대신 복사본을 돌려주는것 (PHP 4이상의 버전은 참조 카운팅을 사용한다) 때문에 퍼포먼스가 나빠지지는 않는다. 반대로 참조 대신에 복사본을 사용하는 것이 대부분 더 낫다. 왜냐하면 참조를 생성하는 것은 가상적으로 복사본을 만드는 데 약간의 시간이 걸리기 때문이다 (그것들이 거대한 배열이나 객체이고 그들 중 하나만 바뀌고 다른것들이 연속적으로 존재한다면, 그리고 동시에 그들 모두를 변경하려한다면 참조를 쓰는것이 더 현명할것이다)

위에서 서술한 것을 검증하기 위해 아래 예제 코드를 보자.
<?php
// now we will change the name. what do you expect?
// you could expect that both $bar1 and $globalref[0] change their names...
$bar1->setName('set from outside');

// as mentioned before this is not the case.
$bar1->echoName();
$globalref[0]->echoName();

/* output:
set from outside
set in constructor */

// let us see what is different with $bar2 and $globalref[1]
$bar2->setName('set from outside');

// luckily they are not only equal, they are the same variable
// thus $bar2->name and $globalref[1]->name are the same too
$bar2->echoName();
$globalref[1]->echoName();

/* output:
set from outside
set from outside */
?>

마지막으로 다음 예제를 보고 이해하도록 하자.

<?php
class A
{
    function 
A($i)
    {
        
$this->value $i;
        
// try to figure out why we do not need a reference here
        
$this->= new B($this);
    }

    function 
createRef()
    {
        
$this->= new B($this);
    }

    function 
echoValue()
    {
        echo 
"<br>","class ",get_class($this),': ',$this->value;
    }
}


class 
B
{
    function 
B(&$a)
    {
        
$this->= &$a;
    }

    function 
echoValue()
    {
        echo 
"<br>","class ",get_class($this),': ',$this->a->value;
    }
}

// try to undestand why using a simple copy here would yield
// in an undesired result in the *-marked line
$a =& new A(10);
$a->createRef();

$a->echoValue();
$a->b->echoValue();
$a->c->echoValue();

$a->value 11;

$a->echoValue();
$a->b->echoValue(); // *
$a->c->echoValue();

/*
output:
class A: 10
class B: 10
class B: 10
class A: 11
class B: 11
class B: 11
*/
?>