私はそれinstanceof
が演算子であり、それis_a
がメソッドであることを認識しています。
この方法はパフォーマンスが遅いですか?何を使いたいですか?
私はそれinstanceof
が演算子であり、それis_a
がメソッドであることを認識しています。
この方法はパフォーマンスが遅いですか?何を使いたいですか?
回答:
更新
とおり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);
間に新たな行動の重要な違いinstanceof
とis_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
is_a
廃止されなかったのですか?
$class = 'Foo'; var_dump($obj instanceof $class);
is_a
vs instanceof
演算子についてもう1つ注意すべき点is_a
は、2番目のパラメーターの式を受け入れることですが、instanceofはしません。たとえば、is_a($object, 'Prefix_'.$name)
動作$object instanceof 'Prefix_'.$name
しないが動作する
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で構文エラーの原因となるので
is_a()とinstanceofのパフォーマンス結果は次のとおりです。
Test name Repeats Result Performance
instanceof 10000 0.028343 sec +0.00%
is_a() 10000 0.043927 sec -54.98%
テストソースはこちらです。
php 7
違いはありません。
instanceof
他のオブジェクトインスタンス、クラスの名前、またはインターフェイスで使用できます。私はそうは思いません(更新:https : //gist.github.com/1455148を参照)is_a()
がインターフェイス(クラス名を表す文字列のみ)動作すると動作する場合は修正してください。
からの例 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)
is_a
と同じようにインターフェイスで動作しますinstanceof
(同じことを言うつもりでしたが、送信する前に確認しましたが、実際に動作します)...
ChrisFの回答に関しては、非推奨でis_a()
はなくなりました、PHP 5.3.0で。このようなことについては、公式の情報源から行くほうが常に安全だと思います。
ダニエル、あなたの質問に関して、パフォーマンスの違いについては言えませんが、その一部は読みやすさに帰着し、作業しやすいと思います。
また、チェックとの否定に関する混乱についても議論されています。たとえば、次のようにします。instanceof
is_a()
instanceof
<?php
if( !($a instanceof A) ) { //... }
?>
対次のis_a()
:
<?php
if( !is_a($a, 'A' ) { //... }
?>
または
<?php
if( is_a($a, 'A') === FALSE) { //... }
?>
編集 ChrisFが彼の回答を削除したように見えますが、私の回答の最初の部分はまだ残っています。
速度に加えて、もう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がそれらを抑制する一方で、起こり得るバグを強調表示します。
最適化は最小限です。そして、コードの可読性、理解可能性、安定性の前では、マイクロ最適化は決して良い答えではありません。
(私は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が役立つことがあります。
パフォーマンスについて話すことはできません-私はまだ何も測定していません-しかし、あなたが試みていることに応じて、 instanceof
ます。最近の私の質問をチェックしてください:
is_a
代わりに使用してしまいました。私はinstanceof
より良い構造が好きです(読みやすいと思います)。可能な限り使用し続けます。
ここから得られたパフォーマンス結果は次のとおりです。
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)
唯一のシナリオがある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に基づいています。