首页 > 编程笔记 > PHP笔记 阅读:12

PHP WeakMap特性的用法(附带实例)

PHP 8 新增 WeakMap 特性,也就是常说的弱映射。

WeakMap 允许创建对象到任意值的映射,同时也不会阻止作为键的对象被垃圾回收。如果某个对象键被垃圾回收,对应键值对将从集合中移除。

WeakMap 新特性非常有用,因为这样一来,开发者就不必担心代码存在内存泄露了。弱映射通常使用在将数据与单个对象实例关联起来,而不强制它们保持活动状态,引用的对象会在失效时自动被垃圾回收。

下面通过实例来理解 WeakMap 特性。

首先定义一个商品类和库房的类,然后看数组中使用情况。
<?php
class Goods{
    public $name;
    public function __construct($name) {
        $this->name=$name;
    }
}

class Storeroom{
    public $rooms=[];
    public function __construct() {
        $this->rooms=[];
    }
    public function addGoods(Goods $goods) {
        $this->rooms[$goods->name]=$goods;
    }
}

$storeroom=new Storeroom();
$juicer=new Goods("果汁机");
$shaver=new Goods("剃须刀");

$storeroom->addGoods($juicer);
$storeroom->addGoods($shaver);

print_count($storeroom->rooms);
echo "<br />";
unset($shaver);
print_count($storeroom->rooms);
echo "<br />";
$storeroomShaver=$storeroom->rooms['剃须刀'];
echo $storeroomShaver->name;
?>
运行程序输出结果如下:

2
2
剃须刀

从结果可以看出,在使用数组时,将商品实例加入库房时,加入的是其克隆体,所以两者互相没有什么干扰。这里虽然使用了 unset($shaver),但是没有对数组中的值产生了什么影响。

如果想实现当对应的商品实例消失的时候,对其引用的类能自动感知。就像商品和库房的关系,如果商品销毁了,比如 unset($shaver),则对应的库房会被清除出来。注意这里把库房清除时,对应的商品是没事的,依旧存在。

下面就通过 WeakMap 来实现上述功能。代码如下:
<?php
class Goods{
    public $name;
    public function __construct($name) {
        $this->name=$name;
    }
}

class Storeroom{
    // 注意这里的数据类型
    public WeakMap $rooms;
    public function __construct() {
        // 这里一定要对其进行实例化
        $this->rooms=new WeakMap();
    }
    public function addGoods(Goods $goods) {
        // 这里一定要以 Object 为索引
        $this->rooms[$goods]=$goods->name;
    }
}

$storeroom=new Storeroom();
$juicer=new Goods("果汁机");
$shaver=new Goods("剃须刀");

$storeroom->addGoods($juicer);
$storeroom->addGoods($shaver);

print count($storeroom->rooms);
echo "<br />";
// 删除其引用
unset($shaver);
print count($storeroom->rooms);
?>
运行程序输出结果如下:

2
1

相关文章