views:

63

answers:

4

I've a reference problem; the example should be more descriptive than me :P

I have a class that has an array of objects and retrieve them through a key (string), like an associative array:

class Collection {

    public $elements;

    function  __construct() {
        $this->elements = array();
    }

    public function get_element($key) {

        foreach($this->elements as $element) {
            if ($element->key == $key) {

                return $element;
                break;
            }
        }
        return null;

    }

    public function add_element ($element) {
        $this->elements[] = $element;
    }

}

Then i have an object (generic), with a key and some variables:

class Element {

    public $key;
    public $another_var;

    public function __construct($key) {
        $this->key = $key;
        $this->another_var = "default";
    }
}

Now, i create my collection:

$collection = new Collection();

$collection->add_element(new Element("test1"));
$collection->add_element(new Element("test2"));

And then i try to change variable of an element contained in my "array":

$element = $collection->get_element("test1");
$element->another_var = "random_string";
echo $collection->get_element("test1")->another_var;

Ok, the output is

random_string

so i know that my object is passed to $element in reference mode.

But if i do, instead:

$element = $collection->get_element("test1");
$element = null; //or $element = new GenericObject();
$element->another_var = "bla";
echo $collection->get_element("test1")->another_var;

the output is

default

like if it lost the reference.

So, what's wrong? I have got the references to the variables of the element and not to the element itself?

Any ideas?

edit: To clarify, i want to "change" the object element with another, but keeping the position in the array.

Now i understand that is not possible in this way :(

+1  A: 

$element has the reference to the object, that is right, but if you do

$element = null; //or $element = new GenericObject();

you assign a new value to $element and you loose the reference to the previous object.

If I do this:

$element = new A();

and then

$element = new B();
$element->foo();

I access the method foo of an object of class B and not A as a new value was assigned to $element.

Felix Kling
+1  A: 

You retreived a reference and assigned it to the variable $element. Then you switched the variable to refer to a new object instead of manipulating the old object.

Fletcher Moore
+1  A: 

Your changing the another_var variable on an element which is pointing to null. This means your not changing the collection element at all. That's why you get the value "default"...

Even if you're working with references, the references themselves are passed by value. This should make it clearer:

$a = new Object();
$b = $a;
$a = null;

$b is still new Object() in this case.

Edit:

If you want to change the object at that position, you have to access your Collection (maybe an associative array) and change the object at that position. You could do this by providing a set_element($key, $value).

<? 

class Collection
{
  private $elements;

  public set_element($key, $value)
  {
     $elements[$key] = $value;
  }

  public get_element($key)
  {
     return $elements[$key];
  }
}

?>
Simon
A: 

When you do this:

$element = null;
$element->another_var = "bla";

you are setting the value of another_var to a null object, because $element is now null. If you try this

$element->another_var = "bla";    
$element = null;

then it should work

Pierre