인스턴스의 클래스가 인터페이스를 구현하는지 확인하고 있습니까?


148

클래스 인스턴스가 주어지면 특정 인터페이스를 구현하는지 여부를 결정할 수 있습니까? 내가 아는 한, 이것을 직접 수행하는 내장 함수는 없습니다. 어떤 옵션이 있습니까 (있는 경우)?

답변:


258
interface IInterface
{
}

class TheClass implements IInterface
{
}

$cls = new TheClass();
if ($cls instanceof IInterface) {
    echo "yes";
}

"instanceof"연산자를 사용할 수 있습니다. 이를 사용하기 위해 왼쪽 피연산자는 클래스 인스턴스이고 오른쪽 피연산자는 인터페이스입니다. 객체가 특정 인터페이스를 구현하면 true를 반환합니다.


102

으로 therefromhere는 지적, 당신은 사용할 수 있습니다 class_implements(). Reflection과 마찬가지로 클래스 이름을 문자열로 지정할 수 있으며 클래스의 인스턴스가 필요하지 않습니다.

interface IInterface
{
}

class TheClass implements IInterface
{
}

$interfaces = class_implements('TheClass');

if (isset($interfaces['IInterface'])) {
    echo "Yes!";
}

class_implements() SPL 확장의 일부입니다.

참조 : http://php.net/manual/en/function.class-implements.php

성능 테스트

몇 가지 간단한 성능 테스트는 각 방법의 비용을 보여줍니다.

주어진 개체의 인스턴스

루프 외부의 객체 구성 (100,000 회 반복)
 ____________________________________________
| class_implements | 반사 | instanceOf |
| ------------------ | ------------ | ------------ |
| 140ms | 290ms | 35ms |
'--------------------------------------------'

루프 내부의 객체 구성 (100,000 회 반복)
 ____________________________________________
| class_implements | 반사 | instanceOf |
| ------------------ | ------------ | ------------ |
| 182ms | 340ms | 83ms | 저렴한 생성자
| 431ms | 607 ms | 338ms | 비싼 생성자
'--------------------------------------------'

클래스 이름 만 주어짐

100,000 회 반복
 ____________________________________________
| class_implements | 반사 | instanceOf |
| ------------------ | ------------ | ------------ |
| 149ms | 295ms | 해당 없음 |
'--------------------------------------------'

비싼 __construct ()는 다음과 같습니다.

public function __construct() {
    $tmp = array(
        'foo' => 'bar',
        'this' => 'that'
    );  

    $in = in_array('those', $tmp);
}

이러한 테스트는 이 간단한 코드를 기반으로 합니다 .


56

nlaq instanceof는 객체가 인터페이스를 구현하는 클래스의 인스턴스인지 테스트하는 데 사용할 수 있다고 지적합니다 .

그러나 instanceof클래스 유형과 인터페이스를 구별하지는 않습니다. 객체가 호출 되는 클래스 인지 알 수 없습니다 IInterface.

PHP에서 리플렉션 API를 사용하여이를보다 구체적으로 테스트 할 수도 있습니다.

$class = new ReflectionClass('TheClass');
if ($class->implementsInterface('IInterface'))
{
  print "Yep!\n";
}

http://php.net/manual/en/book.reflection.php 참조


2
이것은 "정적"클래스에서 사용할 수 있습니다
Znarkus


@therefromhere : 감사합니다, 좋은 팁. 그것은 SPL 확장의 일부입니다. 내 대답은 Reflection 확장을 사용했습니다.
Bill Karwin

3
네임 스페이스를 사용하는 경우 같은 이름을 가진 인터페이스와 클래스간에 모호성이 없으므로 안전하게 instanceof다시 사용할 수 있습니다 .
독감

class_implements()완전히 반영하는 대신 class_implements를 호출 한 다음 in_array를 호출하는 것이 더 빠르기 때문에 +1
Nickolaus

19

향후 검색을 돕기 위해 is_subclass_of 도 좋은 변형입니다 (PHP 5.3.7+ 용).

if (is_subclass_of($my_class_instance, 'ISomeInterfaceName')){
    echo 'I can do it!';
}

5

다음을 수행 할 수도 있습니다.

public function yourMethod(YourInterface $objectSupposedToBeImplementing) {
   //.....
}

인터페이스를 $objectSupposedToBeImplementing구현하지 않으면 복구 가능한 오류가 발생합니다 YourInterface.


3

최신 정보

is_a 기능 은 대안으로 누락되었습니다.

언급 된 방법 중 가장 성능이 좋은 방법을 확인하기 위해 성능 테스트를 수행했습니다.

100k 회 이상의 반복 결과

      instanceof [object] took   7.67 ms | +  0% | ..........
            is_a [object] took  12.30 ms | + 60% | ................
             is_a [class] took  17.43 ms | +127% | ......................
class_implements [object] took  28.37 ms | +270% | ....................................
       reflection [class] took  34.17 ms | +346% | ............................................

실제로 "느낌"을 나타 내기 위해 몇 가지 점을 추가했습니다.

이것에 의해 생성 : https://3v4l.org/8Cog7

결론

경우에 당신은이 물체 를 확인하기 위해 사용 instance of허용 대답에 언급 등이.

확인할 클래스 가있는 경우을 사용하십시오 is_a.

보너스

필요한 인터페이스를 기반으로 클래스를 인스턴스화하려는 경우 사용하는 것이 더 좋습니다 is_a. 생성자가 비어있는 경우 단 하나의 예외가 있습니다.

예: is_a(<className>, <interfaceName>, true);

반환 bool됩니다. 세 번째 매개 변수 " allow_string "을 사용하면 클래스 인스턴스화 하지 않고도 클래스 이름을 확인할 수 있습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.