Ссылочная проблема при возврате объекта из массива в PHP - PullRequest
0 голосов
/ 12 мая 2010

У меня проблема со ссылками;пример должен быть более наглядным, чем я: P

У меня есть класс, который имеет массив объектов и извлекает их через ключ (строку), как ассоциативный массив:

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;
    }

}

Затем у меня есть объект (универсальный), с ключом и некоторыми переменными:

class Element {

    public $key;
    public $another_var;

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

Теперь я создаю свою коллекцию:

$collection = new Collection();

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

И затем я пытаюсь изменить переменнуюэлемент, содержащийся в моем "массиве":

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

Хорошо, вывод

random_string

, поэтому я знаю, что мой объект передается в $ element в режиме ссылки.

Но если я это сделаю, вместо этого:

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

вывод будет

default

, как если бы он потерял ссылку.

Итак, что не так?У меня есть ссылки на переменные элемента, а не на сам элемент?

Есть идеи?

edit: Чтобы уточнить, я хочу "заменить" элемент объекта другим,но сохраняя позицию в массиве.

Теперь я понимаю, что это невозможно таким образом: (

Ответы [ 4 ]

1 голос
/ 12 мая 2010

Вы получили ссылку и присвоили ее переменной $element. Затем вы переключили переменную для ссылки на новый объект вместо того, чтобы манипулировать старым объектом.

1 голос
/ 12 мая 2010

Вы изменили переменную another_var для элемента, который указывает на ноль. Это означает, что вы вообще не меняете элемент коллекции. Вот почему вы получаете значение «по умолчанию» ...

Даже если вы работаете со ссылками, сами ссылки передаются по значению. Это должно прояснить:

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

$b по-прежнему new Object() в этом случае.

Edit:

Если вы хотите изменить объект в этой позиции, вам нужно получить доступ к вашей Коллекции (возможно, ассоциативный массив) и изменить объект в этой позиции. Вы можете сделать это, указав set_element ($ key, $ value).

<? 

class Collection
{
  private $elements;

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

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

?>
1 голос
/ 12 мая 2010

$element имеет ссылку на объект, это правильно, но если вы сделаете

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

Вы присваиваете новое значение $element и теряете ссылку на предыдущий объект.

Если я сделаю это:

$element = new A();

, а затем

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

Я обращаюсь к методу foo объекта класса B, а не A, поскольку для $element.

было присвоено новое значение.
0 голосов
/ 12 мая 2010

Когда вы делаете это:

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

вы устанавливаете значение another_var для нулевого объекта, потому что $ element теперь является нулевым. Если вы попробуете это

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

тогда должно работать

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...