Почему объекты не разрешены в качестве ключей в ассоциативных массивах?

В документации по PHP говорится:

Массивы и объекты не могут использоваться в качестве ключей. Это приведет к предупреждению: Недопустимый тип смещения.

Насколько мне известно, массивы PHP представляют собой упорядоченные хэш-карты. Итак, почему само по себе запрещено использовать объекты в качестве ключей, есть ли причина для этого ограничения? Почему нет возможности реализовать хэш-функцию в классе, чтобы использовать ее как ключ?

В связи с этим, существует ли реализация хэш-карты PHP, которая решает эту проблему?


person rob    schedule 10.12.2012    source источник
comment
Связано: SplObjectStorage, доступный в версии 5.3.   -  person Charles    schedule 10.12.2012
comment
@Charles прекрасно работает, спасибо!   -  person rob    schedule 10.12.2012


Ответы (2)


Ключи должны быть неизменяемыми, чтобы они работали. Если ваши объекты изменяемы, то они не могут быть ключами. Это верно для каждого языка, который их реализует: Java, C# и т.д.

person duffymo    schedule 10.12.2012
comment
Вопрос (я не эксперт, просто любопытно): Если у объектов есть адрес памяти (наверное), то этот адрес памяти не меняется (наверное?) - если такой адрес памяти не меняется, то почему такой адрес не меняется? используется в качестве ключа для этого? - person Voldemort; 10.12.2012
comment
@Омега, интересно. Некоторые языки действительно могут делать что-то подобное. Однако для этого потребуется промежуточное сопоставление преобразования между именем среды выполнения и адресом памяти. Кроме того, это будет иметь последствия для языков со встроенным управлением памятью. - person Jason McCreary; 10.12.2012
comment
@duffymo Я понимаю, что ключи должны быть неизменяемыми, но не должен ли программист использовать только неизменяемые поля класса для генерации хеша? (как, например, в Java) - person rob; 10.12.2012
comment
@JasonMcCreary попал в самую точку в конце. Что, если ваш хэш определен в более широкой области, чем объект внутри? Что происходит, когда ваш объект внутри выпадает из области видимости и удаляется сборщиком мусора? Теперь у вас больше нет способа получить этот ключ, если только вы не сохранили предыдущий адрес памяти. Но подождите, а что, если новый объект будет записан по тому же адресу памяти? Уоу. - person Colin M; 10.12.2012
comment
@rob В объекте PHP все изменяемо. Всегда. Даже частные/защищенные свойства изменяются вне области действия объекта с использованием отражения. Это сделало бы любую честность очень трудной. - person Colin M; 10.12.2012
comment
@duffymo Я не уверен, что согласен с этим: это верно для каждого языка, который их реализует. Конечно, в Java и (iirc) ключи карты python изменяемы. - person Jim; 10.12.2012
comment
Не в Питоне. Вы можете добавить изменяемый ключ к карте в Java, но вы быстро пожалеете об этом. - person duffymo; 10.12.2012
comment
@duffymo Вы можете убедиться, что хэш остается неизменным в Java, используя только неизменяемые поля класса для его создания. Но я признаю, что это опасно, если вы не знаете, что делаете... и поэтому, возможно, хорошо, что это не часть стандартной реализации массива в PHP. - person rob; 11.12.2012

Смотрите @duffymo для ответа.

Обратите внимание, что существует своего рода «обходной путь» с использованием spl_object_hash в качестве ключа. Это возвращает неизменяемую строку, которую можно использовать в качестве ключа, и она будет одинаковой для любого объекта, занимающего этот адрес памяти. (Читайте: spl_object_hash будет возвращать одно и то же значение для одного и того же экземпляра независимо от того, где он вызывается или изменился ли объект)

person Colin M    schedule 10.12.2012
comment
К сожалению, spl_object_hash возвращает разные значения при каждом вызове скрипта, даже если объекты идентичны. Это сделает его несколько неудобным. - person Charles; 10.12.2012
comment
Ну по определению они не идентичны. Это разные объекты. Вам нужно будет реализовать свой собственный метод equals или что-то подобное. Лучший вопрос: зачем вам нужно сравнение перекрестных вызовов в хэш-карте? Почему бы не найти способ создавать уникальные идентификаторы для этих объектов и сохранять их в предназначенной для этого системе? - person Colin M; 10.12.2012