pwm / tc
类型安全的集合。
这个包的官方仓库似乎已经不存在,因此该包已被冻结。
Requires
- php: >=7.1.0
Requires (Dev)
- phpstan/phpstan: ^0.7.0
- phpunit/phpunit: ^6.1
- squizlabs/php_codesniffer: ^3.0
This package is auto-updated.
Last update: 2023-04-28 22:59:13 UTC
README
TypedCollection 是一个简单的抽象集合类,在创建时会检查其元素类型,确保集合的类型安全。
使用 TypedCollection 创建的集合是不可变的、可迭代的、可计数的和可列出的。如果您需要一个可变容器,可以简单地子类化它并添加相关修改器。
该库包含一些具体的实现,例如:Bool、Callable、Float、Int 和 String 集合,但使用任何自定义类型实现自己的自定义类型集合是微不足道的。
目录
原因
随着 PHP7 的出现,该语言开始在一定程度上支持类型声明,因此我们终于可以编写如下代码
function isEven(int $x): bool { return $x % 2 === 0; }
其中 $x 作为返回类型是 bool,因此保证 $x 是一个 int。另一方面,我们仍然不能说像我们想要获取一个整数列表这样的事情,即。
function sum(int[] $xs): int { // can't write int[], only array return array_sum($xs); }
不是有效的 PHP 语法。我们只能在这里使用 array 作为类型声明,因此像 sum([1, 'a', false]) 这样的不合理情况无法被类型检查器捕获。
将上述内容进一步扩展,我们只想保证列表的元素是特定类型的,而不管实际类型是什么。这听起来可能有些奇怪,所以这里有一个例子
$addOne = function (int $x): int { return $x + 1; }; $toUpper = function (string $s): string { return strtoupper($s); }; array_map($addOne, [1, 2, 3]); // [2, 3, 4] array_map($toUpper, ['a', 'b', 'c']); // ['A', 'B', 'C']
Map 不关心其函数参数的类型,也不关心其列表元素的类型。它只关心两件事
- 列表的元素都是同一种类型
- 这种类型与其函数参数的类型相同
使用 PHP 的 array,我们无法保证这两点。使用 TypedCollection,我们可以保证第一点
function map(callable $f, TypedCollection $c) { return array_map($f, $c->toList()); }
保证了 $c 的元素都是同一类型,即。
map($addOne, new IntCollection(1, 2, 3)); // [2, 3, 4] map($toUpper, new StringCollection('a', 'b', 'c')); // ['A', 'B', 'C']
但是
map($addOne, new IntCollection(1, 'a', false)); // Fatal error: Uncaught TypeError
朝着更安全、更健壮的代码迈出的小而重要的一步。
要求
PHP 7.1+
安装
$ composer require pwm/tc
使用
要创建一个具体的类型化集合,我们需要扩展 TypedCollection 并向它提供一个带有类型声明的函数。
例如,以下是一个整数集合的例子
class IntCollection extends TypedCollection { public function __construct(...$ints) { parent::__construct(function (int $int) { return $int; }, $ints); } }
要使用它
$intCollection = new IntCollection(1, 2, 3); // iterable foreach ($intCollection as $element) { assert(is_int($element) === true); } // countable assert(count($intCollection) === 3); // listable assert($intCollection->toList() === [1, 2, 3]);
基本标量类型化集合,即 bool、callable、float、int 和 string,作为库的一部分,方便使用。
它如何工作
技巧是向 TypedCollection 提供一个函数,该函数要求其参数必须是特定类型。为此,我们只需使用 PHP 的内置函数类型声明。这既适用于内置类型,也适用于用户定义的类型(即类)。TypedCollection 还会检查所提供的类型检查函数是否真正进行类型检查,即它会在接收到未类型化的函数时抛出异常。
TypedCollection 实现了 IteratorAggregate 和 Countable 接口,以便于使用。getIterator() 返回一个 Generator,这很好地与集合的不变语义相匹配,即您可以迭代它,访问其元素,而不必访问容器本身。
要获取底层的可变数组表示形式,请使用 toList()。这对于使用 map/filter/reduce 非常有用。
测试
$ vendor/bin/phpunit
$ composer phpcs
$ composer phpstan