da2e/generic-collection

基于PHP的泛型集合实现

v1.3.0 2020-01-10 12:26 UTC

This package is not auto-updated.

Last update: 2024-09-14 11:28:17 UTC


README

这个小型库提供了基于PHP的泛型集合实现。

PHP缺乏泛型(与Java、C++等相反)。问题是您无法控制和确保数组/集合/哈希等元素实现了哪些类型。

示例

$a = [1, 2, new \stdClass(), function () { return 'foo'; }];
$r = 0;

foreach ($a as $v) {
    $r += $v; // here for stdClass and a closure you will get an error: Object of class ... could not be converted to int.
}

例如,在Java中,您可以通过泛型来消除这个问题

List<String> v = new ArrayList<String>();

这个库提供了一个面向对象的解决方案,以便在集合/数组中拥有同质类型。

内置类型

  • DA2E\GenericCollection\Type\ArrayType(对应PHP内置的is_array()函数)。
  • DA2E\GenericCollection\Type\BoolType(对应PHP内置的is_bool()函数)。
  • DA2E\GenericCollection\Type\CallableType(对应PHP内置的is_callable()函数)。
  • DA2E\GenericCollection\Type\FloatType(对应PHP内置的is_float()函数)。
  • DA2E\GenericCollection\Type\IntType(对应PHP内置的is_int()函数)。
  • DA2E\GenericCollection\Type\IterableType(对应PHP内置的is_iterable()函数)。
  • DA2E\GenericCollection\Type\MixedType(通过任何值传递)。
  • DA2E\GenericCollection\Type\NullType(对应PHP内置的is_null()函数)。
  • DA2E\GenericCollection\Type\NumericType(对应PHP内置的is_numeric()函数)。
  • DA2E\GenericCollection\Type\ObjectType(对应PHP内置的is_object()函数)。
  • DA2E\GenericCollection\Type\ResourceType(对应PHP内置的is_resource()函数)。
  • DA2E\GenericCollection\Type\ScalarType(对应PHP内置的is_scalar()函数)。
  • DA2E\GenericCollection\Type\StringType(对应PHP内置的is_string()函数)。

特殊类型

  • DA2E\GenericCollection\Type\CustomType:接受一个带有单个参数的回调函数来构建自定义验证器。例如:
use DA2E\GenericCollection\GCollection;
use DA2E\GenericCollection\Type\CustomType;

$collection = new GCollection(new CustomType(function ($value) {
    return $value === 'foobar';
}));

$collection[] = 'foobar'; // valid
$collection[] = 'bar'; // invalid
  • DA2E\GenericCollection\Type\GCollectionType:嵌套GCollections的类型。例如:
use DA2E\GenericCollection\Type\GCollectionType;
use DA2E\GenericCollection\Type\StringType;
use DA2E\GenericCollection\GCollection;

$collection = new GCollection(new GCollectionType());
$collection[] = new GCollection(new StringType()); // valid
$collection[] = new StringType(); // invalid

ObjectType

ObjectType可以选择接受一个完全限定的类名来验证该值是否实现了给定的类。例如:

$value = new Some\Class\Here();
$type = new DA2E\GenericCollection\Type\ObjectType('Some\Class\Here');
$type->validate($value);

如何使用

  1. 创建一个泛型集合。
  2. 在构造函数中传递该集合的类型。
  3. 泛型集合实现了\ArrayAccess接口,因此只需将/推入元素到数组。
  4. 在向集合添加元素时,会立即对给定类型进行验证。
  5. 如果类型无效,将抛出DA2E\GenericCollection\Exception\InvalidTypeException。

示例

use DA2E\GenericCollection\GCollection;
use DA2E\GenericCollection\Type\StringType;
use DA2E\GenericCollection\Exception\InvalidTypeException;

try {
    $collection = new GCollection(new StringType()); // You can pass an array as 2nd argument as well.
    $collection[] = 'string'; // this one is fine
    $collection[] = 1; // this one will throw an exception
} catch (InvalidTypeException $e) {
    // handle exception
}
  1. 如果您将集合作为参数传递给方法/函数,则可以要求所有元素都应实现确切的类型
function foobar(GCollection $collection) {
    try {
        $collection->elementsShouldBeTypeOf(StringType::class); // If something is wrong InvalidTypeException is thrown
    } catch (InvalidTypeException $e) {
        // handle exception
    }
    
    // ...
}

如果集合包含对象,则还可以进一步确保元素是特定类的实例。

function foobar(GCollection $collection) {
    try {
        $collection->elementsShouldBeTypeOf(ObjectType::class); // This is fine and valid but does not give a lot of information which exactly object is there.
        $collection->elementsShouldBeTypeOf(YourAnyClass::class); // This is more verbose and clear. We know that we expect a concrete YourAnyClass objects.
    } catch (InvalidTypeException $e) {
        // handle exception
    }
    
    // ...
}

GCollectionInterface的附加功能

GCollectionInterface中有许多附加功能(例如map、filter、slice、shuffle等)。请参阅接口以查看所有功能。

map

use DA2E\GenericCollection\GCollection;
use DA2E\GenericCollection\Type\StringType;

$collection = new GCollection(new StringType(), ['a' ,'b']);
$collection->map(function ($item) {
    return $item . '2';
}); // Returns [ 'a2', 'b2', 'c2' ]

filter

use DA2E\GenericCollection\GCollection;
use DA2E\GenericCollection\Type\StringType;

$collection = new GCollection(new StringType(), ['a' ,'b']);
$collection->filter(function ($item) {
    return $item === 'b';
}); // Returns [ 'b' ]

sort

use DA2E\GenericCollection\GCollection;
use DA2E\GenericCollection\Type\StringType;

$collection = new GCollection(new StringType(), ['a' ,'b']);
$collection->sort(function (array $items) {
    rsort($items); // Here you can call any sort function you wish.

    return $items;
}); // Returns [ 'b', 'a' ]