is_aとinstanceofの違いは何ですか?


205

私はそれinstanceofが演算子であり、それis_aがメソッドであることを認識しています。

この方法はパフォーマンスが遅いですか?何を使いたいですか?


15
is_a()は遅くなる可能性がありますが、instanceofをこのように呼び出すことはできませんが、call_user_func()を使用して呼び出すことができます...
KamilTomšíkFeb

回答:


211

更新

とおりPHP 5.3.9の機能がis_a()変更されました。以下の元の回答では、最初の引数としてを受け入れるis_a() 必要があるObjectと述べていますが、PHPバージョン5.3.9以降では、オプションで3番目のブール引数$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以降は非推奨ではなくなったため、心配する必要はありません。

ただし、違いが1つあります。 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廃止されなかったのですか?
セオドアR.スミス

21
@ theodore-r-smithドキュメントによると、「一般的なリクエストによって廃止されていません」php.net/manual/en/migration53.undeprecated.php
Janci

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

39
is_avs instanceof演算子についてもう1つ注意すべき点is_aは、2番目のパラメーターの式を受け入れることですが、instanceofはしません。たとえば、is_a($object, 'Prefix_'.$name)動作$object instanceof 'Prefix_'.$nameしないが動作する
Evan Purkhiser 2013年

6
is_aそもそも廃止されるべきではありませんでした。しかし、今それを修正するのは少し遅れています。問題は、instanceofオペレーターがPHP 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デニス

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要旨にリンクするだけでなく、アップデートを要約してください。それは、学ぼうとしている人々にとって役に立たない。
エリックロバートソン

5

ChrisFの回答に関しては、非推奨is_a() はなくなりました、PHP 5.3.0で。このようなことについては、公式の情報源から行くほうが常に安全だと思います。

ダニエル、あなたの質問に関して、パフォーマンスの違いについては言えませんが、その一部は読みやすさに帰着し、作業しやすいと思います。

また、チェックとの否定に関する混乱についても議論されています。たとえば、次のようにします。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

速度に加えて、もう1つの重要な違いは、エッジケースの処理方法です。

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で直接クラス名を使用できることです

$ ClassのMyClass

より短い

is_a($ a、MyClass :: class)

(わかりました…簡単ではありません)

instanceof(言語構造)とis_aの間の構文上の色分けも(私にとって)役に立ちます。関数の色をより大きな操作に割り当てます。また、ifでの1回限りの使用では、instanceofに括弧を追加する必要はありません。

注:もちろん、MyClass :: classの代わりに、より短い直接文字列を使用できます。

is_a($ a、 'MyClass')

ただし、コードで直接文字列を使用することはお勧めできません

単純な文字列とクラス名を区別できる場合は、構文的照合がより適切で便利です。そして、定数クラス名で名前を変更する方が簡単です。エイリアスで名前空間を使用する場合は特に。

それで、is_a()を使用するのはなぜですか?

同じ理由:可読性と理解不能性。(選択はあなた次第です)または他のブール演算子:is_aは括弧を付けたほうが実用的です。

if($ a AND(!is_a($ a、MyClass :: class)OR is_a($ a、MyOtherClass :: class)))

より読みやすいです:

if($ a AND(!($ a instanceof MyClass)OR($ a intanceof MyOtherClass)))

もう1つの理由は、関数でコールバックを使用する必要がある場合です。(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.