PHP Traversable 类型提示

Posted

技术标签:

【中文标题】PHP Traversable 类型提示【英文标题】:PHP Traversable type hint 【发布时间】:2013-06-06 13:43:00 【问题描述】:

我有一个相对简单的函数,它使用 foreach

function foo($t) 
     $result;
     foreach($t as $val) 
         $result = dosomething($result, $val);
     
     return $result;

我想输入提示,Traversable 似乎正是我需要的输入提示

 function foo(Traversable $t) 

但是,当使用数组时,这会给出E_RECOVERABLE_ERROR(当然可以在foreach 中使用):example

 Argument 1 passed to foo() must implement interface Traversable, array given

有没有办法输入提示或者这是不可能的?

【问题讨论】:

来自手册(您发布的链接):Abstract base interface that cannot be implemented alone. Instead it must be implemented by either IteratorAggregate or Iterator. 我相信你实际上可以使用array作为提示,我会测试我的理论,是的,你可以 @alfasin 因此任何实现Iterator 的类也将匹配Traversable,因为IteratorTraversable 的子类型。基本 OOP 机制 请考虑提供给comment in manual 的解决方案。顺便说一句,I asked a similar question. @Dale 我提前道歉,因为我必须遗漏一些东西:Array don't implement Iterator (AFAIK), and you're trying to use Array, no? 【参考方案1】:

这里有一个错误:#41942。关闭为“不是错误”。由于 php 数组不是对象,它们无法实现接口,因此无法同时输入 arrayTraversable 的提示。

您可以使用iterator_to_arrayArrayIterator 或省略类型提示。请注意,iterator_to_array 会将整个迭代器复制到一个数组中,因此可能效率低下。

// These functions are functionally equivalent but do not all accept the same arguments
function foo(array $a)  foobar($a); 
function bar(Traversable $a)  foobar($a); 
function foobar($a) 
    foreach($a as $key => $value) 
    


$array = array(1,2,3)
$traversable = new MyTraversableObject();

foo($array);
foo(iterator_to_array($traversable));

bar(new ArrayIterator($array));
bar($traversable);

foobar($array);
foobar($traversable);

【讨论】:

你也可以通过foo(new ArrayIterator(array(1,2,3))将数组转换为对象。【参考方案2】:

问题是,数组不是对象,所以它们不能实现接口。所以你不能同时输入提示,arrayTraversable

【讨论】:

是否还有其他 PHP 原生实体可以在 foreach 中使用但不实现 Traversable 不,但您可以编写自己的类来实现IteratorAggregateIterator,并且它们扩展Traversable 但就是这样:foreach 中的所有对象都可迭代。如果对象实现了Traversable,则将遍历迭代器(或聚合迭代器),否则将遍历对象的公共属性php.net/manual/en/control-structures.foreach.php【参考方案3】:

同样的问题。我已经放弃了,我只是手动编写函数中的所有内容。

这应该会给你你想要的功能:

function MyFunction($traversable)

    if(!$traversable instanceof Traversable && !is_array($traversable))
    
        throw new InvalidArgumentException(sprintf(
            'Myfunction($traversable = %s): Invalid argument $traversable.'
            ,var_export($traversable, true)
       ));
    

编辑

如果您只想显示$traversable 的类型。如果您希望在子类中继承该功能。

public function MyMethod($traversable)

    if(!$traversable instanceof Traversable && !is_array($traversable))
    
        throw new InvalidArgumentException(sprintf(
            '%s::MyMethod($traversable): Invalid argument $traversable of type `%s`.'
            ,get_class($this)
            ,gettype($traversable)
       ));
    

【讨论】:

【参考方案4】:

PHP 7.1 为此引入了iterable type declaration,它接受\Traversable 的数组和实例。

在以前的版本中,您必须省略类型声明。

【讨论】:

以上是关于PHP Traversable 类型提示的主要内容,如果未能解决你的问题,请参考以下文章

PHP预定义接口一:Traversable

是否有可能懒散地获得Traversable的所有上下文?

Haskell中Traversable冒泡排序中的无限循环

[Compose] 19. Leapfrogging types with Traversable

如何合并两个 MySQL 结果?

了解Scala集合概念,掌握Traversable的用法