继承ArrayObject的类remove方法失效?问题原因及修复方法咨询
问题根源与修复方案
首先,咱们拆解下你遇到的问题:继承ArrayObject的类里remove方法没生效,本质上大概率是你没有真正修改ArrayObject实例的内部存储,而是在操作它的副本。
举个典型的错误写法(我猜你可能类似这么写的):
class MyCollection extends ArrayObject { public function __construct(array $items = []) { parent::__construct($items); } public function contains($item) { return in_array($item, $this->getArrayCopy()); } public function remove($item) { // 这里拿到的是内部数组的副本,不是原实例的引用 $items = $this->getArrayCopy(); foreach ($items as $key => $value) { if ($value === $item) { unset($items[$key]); // 只修改了副本,原实例完全没变化 } } // 关键:没有把修改后的副本同步回原实例! } }
为什么会这样?
ArrayObject::getArrayCopy()方法返回的是内部数组的值副本,不是引用。你在这个副本上做的任何修改,都不会影响原ArrayObject实例的内容——相当于你在草稿纸上改东西,原文件根本没碰。
怎么修复?
有两种靠谱的修复方式,选哪种看你的习惯:
方式一:直接操作原实例
遍历ArrayObject本身,用它的内置方法offsetUnset()或者直接数组索引移除元素:
public function remove($item) { foreach ($this as $key => $value) { if ($value === $item) { // 二选一都可以,效果一致 $this->offsetUnset($key); // 或者 unset($this[$key]); } } }
方式二:修改副本后同步回原实例
如果你更习惯操作普通数组,修改完副本后用exchangeArray()把新数组替换原实例的内部存储:
public function remove($item) { $items = $this->getArrayCopy(); foreach ($items as $key => $value) { if ($value === $item) { unset($items[$key]); } } // 把修改后的数组注入回原实例 $this->exchangeArray($items); }
测试验证
修复后再跑你的测试代码:
$col = new MyCollection(['apple', 'banana', 'cherry']); $col->remove('banana'); var_dump($col->contains('banana')); // 现在会输出false,符合预期
另外提个小细节:如果你的集合里有重复元素,上面的代码会移除所有匹配项;如果只想移除第一个匹配的,在找到元素后加个break就行。
内容的提问来源于stack exchange,提问作者Jacobian
相关产品推荐
相关产品推荐

