is_a와 instanceof의 차이점은 무엇입니까?


205

나는 그것이 instanceof연산자이고 그것이 is_a방법 이라는 것을 알고 있습니다.

방법이 성능이 느립니까? 무엇을 사용 하시겠습니까?


15
is_a ()는 느려질 수 있지만 instanceof를 이런 식으로 호출 할 수없는 동안 call_user_func ()를 사용하여 호출 할 수 있습니다.
Kamil Tomšík

답변:


211

최신 정보

현재 PHP 5.3.9 의 기능이 is_a()변경되었습니다. 아래의 원래 답변 은 첫 번째 인수로을 수락 is_a() 해야Object 하지만 PHP 버전> = 5.3.9 는 문자열 클래스 이름을 비교할 수 있는 선택적 세 번째 부울 인수 $allow_string(기본값은 false)를 허용합니다.

class MyBaseClass {}
class MyExtendingClass extends MyBaseClass {}

// Original behavior, evaluates to false.
is_a(MyExtendingClass::class, MyBaseClass::class);

// New behavior, evaluates to true.
is_a(MyExtendingClass::class, MyBaseClass::class, true);

사이의 새로운 동작의 차이점 instanceofis_a()instanceof반면, 항상 목표 (확장 클래스를 포함) 지정된 클래스의 객체 인스턴스인지 확인합니다 is_a()에만이 경우 개체가 인스턴스화해야합니다 $allow_string인수의 기본 값으로 설정됩니다 false.


실물

실제로 는 언어 구조 is_a인 반면 함수 instanceof입니다. is_a(함수 호출을 실행하는 모든 오버 헤드가 있기 때문에) 상당히 느려 지지만 전체 실행 시간은 두 방법 모두에서 최소입니다.

더 이상 5.3부터 더 이상 사용되지 않으므로 걱정할 필요가 없습니다.

그러나 한 가지 차이점이 있습니다. is_a함수는 객체를 매개 변수 1로, 문자열 (변수, 상수 또는 리터럴)을 매개 변수 2로 사용합니다.

is_a($object, $string); // <- Only way to call it

instanceof 객체를 매개 변수 1로 사용하고 클래스 이름 (변수), 객체 인스턴스 (변수) 또는 클래스 식별자 (따옴표없이 작성된 클래스 이름)를 매개 변수 2로 사용할 수 있습니다.

$object instanceof $string;      // <- string class name
$object instanceof $otherObject; // <- object instance
$object instanceof ClassName;    // <- identifier for the class

36
더 이상 사용되지 않는 이유는 무엇 is_a입니까?
Theodore R. Smith

21
@ theodore-r-smith 문서에 따르면 "인기있는 요청에 의해 폐기되지 않았다
Janci

3
@danip$class = 'Foo'; var_dump($obj instanceof $class);
ircmaxell

39
연산자 is_ainstanceof연산자 에 대해 더주의해야 할 점은 is_a두 번째 매개 변수에 대한 표현식을 허용하지만 instanceof는 그렇지 않다는 것입니다. 예를 들어 is_a($object, 'Prefix_'.$name)작동 $object instanceof 'Prefix_'.$name하지 않는 동안
Evan Purkhiser

6
is_a처음부터 더 이상 사용되지 않아야합니다. 그래도 지금 고치기에는 조금 늦었습니다. 문제는 instanceofPHP 4에서 연산자가 구문 오류를 던지고 is_a, 연산자가 소개 된 것과 정확히 같은 시점에 사용되지 않기 때문에 E_STRICT를 던지지 않고 PHP 4와 5의 코드를 작성하는 것이 불가능 해졌다는 것입니다. if (version_compare(PHP_VERSION, 5) >= 0) { /* use instanceof */ } else { /* use is_a */ }PHP 4에서도 여전히 문법 오류가 발생하기 때문에 할 수 없습니다 .
meustrus

47

is_a ()instanceof 의 성능 결과는 다음과 같습니다 .

Test name       Repeats         Result          Performance     
instanceof      10000           0.028343 sec    +0.00%
is_a()          10000           0.043927 sec    -54.98%

테스트 소스는 여기에 있습니다 .


6
다시 말해, 차이는 10000 회 사용시 ~ 0.015 초를 절약해야하는 경우에만 중요합니다.
CJ 데니스

1
현재 php 7로서는 차이가 없습니다.
MAX

@CJDennis 경험에 의하면 모든 사람이 이와 같이 생각하면 최종 제품이 예상보다 느려질 것입니다. (소프트 + OS + 서버 최적화되지 않음). 추가 된 시간이 항상 선형은 아니지만 지수 일 수 있음을 기억하십시오. 항상 성능을 염두에 두십시오.
Toto

@Toto 숙련 된 개발자가 초보자로부터 배울 수있는 내용에 대한 훌륭한 블로그 게시물이 있습니다. 바라건대 오른쪽 상단에서 볼 수 있습니다. 조기 최적화에주의하십시오! 문제가 된 후에 만 타이밍 문제 를 해결하십시오 ! 성능이 그대로 만족스러운 경우 변경하는 데 시간을 소비하지 마십시오!
CJ Dennis

10

instanceof다른 객체 인스턴스, 클래스 이름 또는 인터페이스와 함께 사용할 수 있습니다. 나는 그것이 is_a()인터페이스 (클래스 이름을 나타내는 문자열 만)와 함께 작동 한다고 생각하지 않지만 그렇게 하면 나를 수정하십시오. (업데이트 : https://gist.github.com/1455148 참조 )

php.net의 예 :

interface MyInterface
{
}

class MyClass implements MyInterface
{
}

$a = new MyClass;
$b = new MyClass;
$c = 'MyClass';
$d = 'NotMyClass';

var_dump($a instanceof $b); // $b is an object of class MyClass
var_dump($a instanceof $c); // $c is a string 'MyClass'
var_dump($a instanceof $d); // $d is a string 'NotMyClass'

출력 :

bool(true)
bool(true)
bool(false)

3
is_a인터페이스와 동일한 방식으로 작업합니다 (같은 내용 instanceof을 말했지만 제출하기 전에 확인했지만 실제로 작동합니다) ...
ircmaxell

2
-1 요점에 연결하는 대신 업데이트를 요약하십시오. 배우려는 사람들에게는 도움이되지 않습니다.
Erick Robertson

5

ChrisF의 답변과 관련하여 is_a() 더 이상 PHP 5.3.0부터 더 이상 사용되지 않습니다 . 나는 이런 것들을 위해 공식 소스를 이용하는 것이 항상 더 안전하다는 것을 알았습니다.

귀하의 질문에 대해 Daniel은 성능 차이에 대해 말할 수 없지만 그중 일부는 가독성과 함께 다루기가 더 쉽다는 것을 알게 될 것입니다.

또한 수표를 무효화하는 것에 대한 혼란에 대한 토론이 있습니다. 예를 들어, 위해 당신이 할 것입니다 :instanceofis_a()instanceof

<?php
if( !($a instanceof A) ) { //... }
?>

다음에 대한 대 is_a():

<?php
if( !is_a($a, 'A' ) { //... }
?>

또는

<?php
if( is_a($a, 'A') === FALSE) { //... }
?>

편집 ChrisF가 자신의 답변을 삭제 한 것처럼 보이지만 내 답변의 첫 부분은 여전히 ​​유효합니다.


5

속도 외에도 또 다른 중요한 차이점은 에지 케이스를 처리하는 방법입니다.

is_a($x1, $x2) // fatal error if x2 is not a string nor an object
$x1 instanceof $x2  // returns false even if $x2 is int, undefined, etc.

따라서 is_a ()는 가능한 버그를 강조 표시하지만 instanceof는이를 억제합니다.


2

최적화는 최소입니다. 그리고 마이크로 최적화는 코드의 가독성, 이해성 및 안정성 앞에서 절대 좋은 대답이 아닙니다.

(개인적으로 나는 instanceof 를 선호하지만, 선택은 당신입니다;))

주요 차이점은 instanceof 와 함께 직접 클래스 이름을 사용할 수 있다는 것입니다

MyClass의 인스턴스

보다 짧다

is_a ($ a, MyClass :: class)

(좋아… 사소하지 않다.)

instanceof (언어 구조)와 is_a 사이의 구문 색이 유용합니다 (나에게도). 더 큰 작업에 기능 색상을 부여합니다. 그리고 if의 단일 사용을 위해 instanceof는 더 많은 괄호가 필요하지 않습니다.

참고 : 물론 MyClass :: class 대신 더 짧은 직접 문자열을 사용할 수 있습니다.

is_a ($ a, 'MyClass')

그러나 코드에서 직접 문자열을 사용하는 것은 좋은 습관이 아닙니다 .

간단한 문자열과 클래스 이름을 구별 할 수 있으면 구문 조합이 더 유용합니다. 상수 클래스 이름으로 이름을 변경하는 것이 더 쉽습니다. 별명과 함께 네임 스페이스를 사용하는 경우 특히 유용합니다.

그래서 is_a () 사용 합니까?

같은 raison : 가독성과 이해할 수없는. (선택은 당신입니다) ! 또는 다른 부울 연산자 : is_a 는 괄호로 더 실용적입니다.

if ($ a AND (! is_a ($ a, MyClass :: class) 또는 is_a ($ a, MyOtherClass :: class)))

보다 읽기 쉽다 :

if ($ a AND (! (MyClass의 인스턴스 $ a 또는 MyOtherClass의 $ a 인스턴스)))

또 다른 좋은 이유는 함수에서 콜백을 사용해야 할 때입니다. ( array_map … 과 같은 ) instanceof 는 함수가 아니며 언어 구성이므로 콜백으로 사용할 수 없습니다.

이러한 경우 is_a 가 유용 할 수 있습니다.


1

성능에 대해 말할 수는 없습니다. 아직 아무것도 측정하지 않았습니다.하지만 시도한 내용에 따라에 제한이 instanceof있습니다. 최근에 내 질문을 확인하십시오.

클래스 상수로 실패한 PHP 'instanceof'

is_a대신에 사용 했습니다. 나는 instanceof더 나은 구조를 좋아하고 (더 잘 읽은 것 같아) 계속 사용할 수있는 곳에서 계속 사용할 것이다.


1

여기에서 얻은 성과입니다 여기가 :

instanceof 가 더 빠르다.

기능

function method_1($a = null) { 
    return is_object($a) && is_a($a, 'Example');
}

function method_2($a = null) {
    return is_a((object) $a, 'Example');
}

function method_3($a = null) {
    return $a instanceof 'Example';
}

시간 (각 5000 회 실행)

0.00573397 // method_1(5) 
0.01437402 // method_2(5) 
0.00376201 // method_3(5)

1

is_a()작동하고 instanceof실패 하는 시나리오가 있습니다 .

instanceof 리터럴 클래스 이름 또는 객체 또는 문자열 (클래스 이름이있는) 인 변수가 올바른 인수로 예상됩니다.

그러나 함수 호출에서 클래스 이름의 문자열을 제공하려는 경우 작동하지 않으며 구문 오류가 발생합니다.

그러나 동일한 시나리오가 제대로 작동합니다. is_a() .

예:

<?php

function getClassName() : string
{
    return "Foobar";
}

class Foobar
{
    private $xyz;

}

$x = new Foobar();

// this works of course
var_dump($x instanceof Foobar);

// this creates a syntax error
var_dump($x instanceof getClassName());

// this works
var_dump(is_a($x, getClassName()));

이것은 PHP 7.2.14를 기반으로합니다.

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