【问题标题】:Why are objects not allowed as keys in associative arrays?为什么不允许对象作为关联数组中的键?
【发布时间】:2012-12-10 01:57:17
【问题描述】:

PHP documentation 声明:

数组和对象不能用作键。这样做会导致警告:Illegal offset type。

AFAIK,PHP 数组是有序的哈希映射。那么,为什么本身就禁止使用对象作为键,有这个限制的原因吗?为什么不可能在一个类中实现一个散列函数来将其用作键?

在相关说明中,是否有解决此问题的哈希映射的 PHP 实现?

【问题讨论】:

  • 相关:SplObjectStorage,在 5.3 中可用。
  • @Charles 就像一个魅力,谢谢!

标签: php hashmap associative-array


【解决方案1】:

键必须是不可变的才能正常工作。如果您的对象是可变的,那么它们就不能是键。在实现它们的每种语言中都是如此:Java、C# 等。

【讨论】:

  • 问题(我不是专家,只是好奇):如果对象有一个内存地址(我猜),这个内存地址不会改变(我猜?) - 如果这样的内存地址没有t 改变,为什么这样的地址不用作这个的关键?
  • @Omega,很有趣。有些语言可能确实会做这样的事情。但是,这需要 runtime 名称和内存地址之间的中间转换映射。此外,这将对具有内置内存管理的语言产生影响。
  • @duffymo 我知道键必须是不可变的,但是程序员不应该只使用类的不可变字段来生成散列吗? (例如在 Java 中)
  • @JasonMcCreary 最后一针见血。如果您的散列定义在比对象范围更广的范围内怎么办?当您的对象超出范围并被垃圾收集时会发生什么?你现在再也没有办法得到那个键了,除非你碰巧存储了以前的内存地址。但是等等,如果一个新对象被写入同一个内存地址怎么办?嗯。
  • @rob PHP 对象中的一切都是可变的。总是。甚至私有/受保护的属性在使用反射的对象范围之外也是可变的。这将使任何形式的完整性变得非常困难。
【解决方案2】:

请参阅@duffymo 以获得答案。

请注意,通过使用spl_object_hash 作为您的密钥,有一种“解决方法”。这将返回一个字符串,该字符串是不可变的,可以用作键,并且对于占用该内存地址的任何对象都是相同的。 (阅读:spl_object_hash 将为同一个实例返回相同的值,无论它在哪里调用或对象是否已更改)

【讨论】:

  • 不幸的是,spl_object_hash 在每次脚本调用时返回不同的值,即使对象相同。这样会有点不方便。
  • 好吧,根据定义,它们并不相同。它们是不同的对象。您需要实现自己的 equals 方法或类似方法。更好的问题:为什么需要在哈希映射中进行交叉调用比较?为什么不找到一种方法来为这些对象创建唯一标识符并将它们持久保存在专门用于此目的的系统中?
猜你喜欢
  • 2021-09-26
  • 1970-01-01
  • 2012-02-16
  • 2020-01-30
  • 1970-01-01
  • 1970-01-01
  • 2018-07-19
  • 2019-03-02
  • 1970-01-01
相关资源
最近更新 更多