ฉันรู้ว่าinstanceof
เป็นผู้ดำเนินการและis_a
เป็นวิธีการ
วิธีนี้ช้าลงในประสิทธิภาพหรือไม่? คุณต้องการใช้อะไร
ฉันรู้ว่าinstanceof
เป็นผู้ดำเนินการและis_a
เป็นวิธีการ
วิธีนี้ช้าลงในประสิทธิภาพหรือไม่? คุณต้องการใช้อะไร
คำตอบ:
ปรับปรุง
ตั้งแต่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);
ความแตกต่างที่สำคัญในการทำงานใหม่ระหว่างinstanceof
และis_a()
คือการที่instanceof
จะตรวจสอบว่าเป้าหมายเป็นวัตถุ instantiated ของชั้นที่กำหนด (รวมถึงการขยายชั้นเรียน) ในขณะที่is_a()
เพียงต้องการว่าวัตถุที่ถูก instantiated เมื่ออาร์กิวเมนต์ถูกตั้งค่าเริ่มต้นของ$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
is_a
ชดเชย
$class = 'Foo'; var_dump($obj instanceof $class);
is_a
vs instanceof
โอเปอเรเตอร์คือการis_a
ยอมรับนิพจน์สำหรับพารามิเตอร์ที่สองในขณะที่อินสแตนซ์ของเคย ตัวอย่างเช่นการis_a($object, 'Prefix_'.$name)
ทำงานในขณะที่$object instanceof 'Prefix_'.$name
ไม่
is_a
ไม่ควรเลิกใช้ตั้งแต่แรก มันสายไปหน่อยที่จะซ่อมมันตอนนี้ ปัญหาคือinstanceof
ผู้ประกอบการพ่นข้อผิดพลาดทางไวยากรณ์ใน PHP 4 และเนื่องจากis_a
ถูกคัดค้านในเวลาเดียวกับที่ผู้ประกอบการได้เปิดตัวมันเป็นไปไม่ได้ที่จะเขียนรหัสสำหรับทั้ง PHP 4 และ 5 โดยไม่ต้องโยน E_STRICT คุณไม่สามารถทำได้if (version_compare(PHP_VERSION, 5) >= 0) { /* use instanceof */ } else { /* use is_a */ }
เพราะมันจะทำให้เกิดข้อผิดพลาดทางไวยากรณ์ใน PHP 4
นี่คือผลการดำเนินงานของis_a ()และตัวอย่างของ :
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) ) { //... }
?>
vs ต่อไปนี้สำหรับis_a()
:
<?php
if( !is_a($a, 'A' ) { //... }
?>
หรือ
<?php
if( is_a($a, 'A') === FALSE) { //... }
?>
แก้ไขดูเหมือนว่า ChrisF จะลบคำตอบของเขา แต่ส่วนแรกของคำตอบของฉันยังคงอยู่
นอกจากความเร็วแล้วความแตกต่างที่สำคัญอีกอย่างก็คือวิธีจัดการกับเคสแบบขอบ
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 () จะเน้นข้อบกพร่องที่เป็นไปได้ขณะที่อินสแตนซ์ของยับยั้งพวกเขา
การเพิ่มประสิทธิภาพน้อยที่สุด และการเพิ่มประสิทธิภาพขนาดเล็กนั้นไม่ใช่คำตอบที่ดีจริง ๆ ต่อหน้าความสามารถในการอ่านความเข้าใจและความเสถียรของโค้ด
(โดยส่วนตัวแล้วฉันต้องการอินสแตนซ์ก่อน แต่ตัวเลือกเป็นของคุณ))
ความแตกต่างหลักคือความเป็นไปได้ที่จะใช้ชื่อคลาสโดยตรงกับอินสแตนซ์ของ
$ a instanceof MyClass
สั้นกว่า
is_a ($ a, MyClass :: คลาส)
(ตกลง…มันไม่สำคัญเลย)
สีของไวยากรณ์ระหว่าง instanceof (โครงสร้างภาษา) และ is_a นั้นมีประโยชน์เช่นกัน (สำหรับฉัน) ปล่อยให้สีของฟังก์ชั่นทำงานใหญ่ขึ้น และสำหรับการใช้งานครั้งเดียวในถ้าอินสแตนซ์ของ dos ไม่จำเป็นต้องใช้วงเล็บมากขึ้น
หมายเหตุ: แน่นอนแทนที่จะเป็นคลาส MyClass :: คุณสามารถใช้สตริงโดยตรงที่สั้นกว่า:
is_a ($ a 'MyClass')
แต่ใช้สตริงโดยตรงในรหัสไม่ได้เป็นวิธีที่ดี
การจัดเรียงทางไวยากรณ์นั้นดีกว่าและมีประโยชน์มากกว่าหากคุณสามารถสร้างความแตกต่างระหว่างชื่อสตริงและคลาสอย่างง่าย และง่ายต่อการเปลี่ยนชื่อด้วยชื่อคงที่ พิเศษถ้าคุณใช้เนมสเปซกับนามแฝง
ดังนั้นเราจะใช้is_a () ได้อย่างไร
สำหรับ raison ที่เหมือนกัน: การอ่านและ undestandability (เป็นทางเลือกของคุณ) พิเศษเมื่อใช้กับ! หรือตัวดำเนินการบูลีนอื่น ๆ : is_aดูเหมือนจะเป็นจริงมากขึ้นด้วยวงเล็บ
if ($ a AND (! is_a ($ a, MyClass :: class) หรือ is_a ($ a, MyOtherClass :: class)))
สามารถอ่านได้มากกว่า:
if ($ a AND (! ($ a instanceof MyClass) หรือ ($ a intanceof MyOtherClass))
อีกเหตุผลที่ดีคือเมื่อคุณต้องการใช้โทรกลับในฟังก์ชั่น (เช่นarray_map ... ) instanceofไม่ใช่ฟังก์ชัน แต่เป็นโครงสร้างภาษาดังนั้นคุณจึงไม่สามารถใช้เป็น callback ได้
ในกรณีเหล่านี้is_aอาจมีประโยชน์
ฉันไม่สามารถพูดเพื่อให้ได้ประสิทธิภาพ - ฉันไม่ได้วัดอะไรเลย - แต่ขึ้นอยู่กับสิ่งที่คุณกำลังพยายามที่มีข้อ จำกัด instanceof
ด้วย ลองดูคำถามของฉันเมื่อเร็ว ๆ นี้เกี่ยวกับ:
PHP '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