반복 가능한 객체 및 배열 유형 힌트?
배열에 대한 유형 힌트가 있거나 is_array()
변수의 배열 여부를 확인하는 데 사용하는 많은 함수가 있습니다 .
이제 반복 가능한 객체를 사용하기 시작했습니다. 그들은 Iterator
또는 IteratorAggregate
. 유형 힌트를 통과하면 배열로 허용 is_array()
됩니까?
내 코드를 수정해야하는 경우, 일반적인 종류가 있습니까 is_iterable()
, 아니면 다음과 같이해야합니까?
if ( is_array($var) OR $var instance_of Iterable OR $var instanceof IteratorAggregate ) { ... }
어떤 다른 반복 가능한 인터페이스가 있습니까?
instanceof Iterator
, PHP에는 Iterable
인터페이스 가 없다고 생각합니다 . Traversable
그래도 인터페이스 가 있습니다 . Iterator
그리고 IteratorAggregate
둘 다 확장합니다 Traversable
(그리고 AFAIK는 그렇게 할 유일한 사람입니다).
그러나 아니요, 구현하는 객체 Traversable
는 is_array()
검사를 통과하지 못하며 내장 is_iterable()
기능도 없습니다. 사용할 수있는 수표는
function is_iterable($var) {
return (is_array($var) || $var instanceof Traversable);
}
명확하게하기 위해, 모든 PHP는 객체의 foreach와 반복,하지만 할 수있는 몇 가지 그들의 구현 Traversable
. 따라서 제시된 is_iterable
함수는 foreach가 처리 할 수있는 모든 것을 감지하지 않습니다.
PHP 7.1.0 은 이러한 목적을 위해 특별히 설계된 iterable
pseudo-type 및 is_iterable()
함수를 도입 했습니다 .
이것은 […] 새로운
iterable
의사 유형을 제안합니다 . 이 유형은callable
하나의 단일 유형 대신 여러 유형을 허용 하는와 유사 합니다.
iterable
array
또는 객체 구현을 허용합니다Traversable
. 이 두 유형은 모두 반복 가능하며 생성기 내에서foreach
사용할 수 있습니다yield
.
function foo(iterable $iterable) {
foreach ($iterable as $value) {
// ...
}
}
이 […]는 또한
is_iterable()
부울을 반환 하는 함수 를 추가true
합니다. 값이 반복 가능하고 다른 값에 대해iterable
의사 유형에서 허용되는 경우false
.
var_dump(is_iterable([1, 2, 3])); // bool(true)
var_dump(is_iterable(new ArrayIterator([1, 2, 3]))); // bool(true)
var_dump(is_iterable((function () { yield 1; })())); // bool(true)
var_dump(is_iterable(1)); // bool(false)
var_dump(is_iterable(new stdClass())); // bool(false)
stdClass의 인스턴스가 foreach 루프에서 작동하기 때문에 실제로 stdClass에 대한 검사를 추가해야했지만 stdClass는 Traversable을 구현하지 않습니다.
function is_iterable($var) {
return (is_array($var) || $var instanceof Traversable || $var instanceof stdClass);
}
나는 "반복성"을 테스트하기 위해 간단한 방법을 사용합니다.
function is_iterable($var) {
set_error_handler(function ($errno, $errstr, $errfile, $errline, array $errcontext)
{
throw new \ErrorException($errstr, null, $errno, $errfile, $errline);
});
try {
foreach ($var as $v) {
break;
}
} catch (\ErrorException $e) {
restore_error_handler();
return false;
}
restore_error_handler();
return true;
}
반복 불가능한 변수를 반복하려고하면 PHP가 경고를 표시합니다. 반복을 시도하기 전에 사용자 지정 오류 처리기를 설정하면 오류를 예외로 변환하여 try / catch 블록을 사용할 수 있습니다. 나중에 프로그램 흐름을 방해하지 않도록 이전 오류 처리기를 복원합니다.
다음은 작은 테스트 케이스입니다 (PHP 5.3.15에서 테스트 됨).
class Foo {
public $a = 'one';
public $b = 'two';
}
$foo = new Foo();
$bar = array('d','e','f');
$baz = 'string';
$bazinga = 1;
$boo = new StdClass();
var_dump(is_iterable($foo)); //boolean true
var_dump(is_iterable($bar)); //boolean true
var_dump(is_iterable($baz)); //boolean false
var_dump(is_iterable($bazinga)); //bolean false
var_dump(is_iterable($boo)); //bolean true
불행히도 당신은 이것에 대해 타입 힌트를 사용할 수 없을 것이고 그 일을해야 할 것이다 is_array($var) or $var instanceof ArrayAccess
. 이것은 알려진 문제이지만 아직 해결되지 않았습니다. 적어도 방금 테스트 한 PHP 5.3.2에서는 작동하지 않습니다.
반복 가능한 객체를 사용하도록 전환하면 유형 힌트를 사용할 수 있습니다.
protected function doSomethingWithIterableObject(Iterator $iterableObject) {}
또는
protected function doSomethingWithIterableObject(Traversable $iterableObject) {}
그러나 이것은 반복 가능한 객체와 배열을 동시에 받아들이는 데 사용할 수 없습니다. 정말로 그렇게하고 싶다면 다음과 같은 래퍼 함수를 만들 수 있습니다.
// generic function (use name of original function) for old code
// (new code may call the appropriate function directly)
public function doSomethingIterable($iterable)
{
if (is_array($iterable)) {
return $this->doSomethingIterableWithArray($iterable);
}
if ($iterable instanceof Traversable) {
return $this->doSomethingIterableWithObject($iterable);
}
return null;
}
public function doSomethingIterableWithArray(array $iterable)
{
return $this->myIterableFunction($iterable);
}
public function doSomethingIterableWithObject(Iterator $iterable)
{
return $this->myIterableFunction($iterable);
}
protected function myIterableFunction($iterable)
{
// no type checking here
$result = null;
foreach ($iterable as $item)
{
// do stuff
}
return $result;
}
ReferenceURL : https://stackoverflow.com/questions/3584700/iterable-objects-and-array-type-hinting
'programing' 카테고리의 다른 글
makefile에서 -I와 -L의 차이점은 무엇입니까? (0) | 2021.01.18 |
---|---|
감사와 로깅의 차이점은 무엇입니까? (0) | 2021.01.18 |
C # 구조체 new StructType () 대 default (StructType) (0) | 2021.01.18 |
getElementById ()는 요소가 존재하더라도 null을 반환합니다. (0) | 2021.01.18 |
asp.net-mvc의 서버에서 텍스트 파일을 읽는 가장 좋은 방법은 무엇입니까? (0) | 2021.01.18 |