Tôi biết rằng đó instanceof
là một toán tử và đó is_a
là một phương pháp.
Là phương pháp chậm hơn trong hiệu suất? Bạn thích sử dụng cái gì?
Tôi biết rằng đó instanceof
là một toán tử và đó is_a
là một phương pháp.
Là phương pháp chậm hơn trong hiệu suất? Bạn thích sử dụng cái gì?
Câu trả lời:
Cập nhật
Kể từ phiên bản PHP 5.3.9 , chức năng của is_a()
đã thay đổi. Câu trả lời ban đầu bên dưới nói rằng is_a()
phải chấp nhận một Object
đối số đầu tiên, nhưng các phiên bản PHP> = 5.3.9 hiện chấp nhận một đối số boolean thứ ba tùy chọn $allow_string
(mặc định false
) để cho phép so sánh các tên lớp chuỗi thay thế:
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);
Sự khác biệt chính trong hành vi mới giữa instanceof
và is_a()
là instanceof
sẽ luôn kiểm tra xem mục tiêu có phải là đối tượng được khởi tạo của lớp được chỉ định (bao gồm cả các lớp mở rộng) hay không, trong khi is_a()
chỉ yêu cầu đối tượng được khởi tạo khi $allow_string
đối số được đặt thành giá trị mặc định false
.
Nguyên
Trên thực tế, is_a
là một chức năng, trong khi đó instanceof
là một cấu trúc ngôn ngữ. is_a
sẽ chậm hơn đáng kể (vì nó có toàn bộ chi phí thực hiện lệnh gọi hàm), nhưng thời gian thực hiện chung là tối thiểu trong cả hai phương thức.
Nó không còn bị phản đối kể từ ngày 5.3, vì vậy không có gì phải lo lắng ở đó.
Tuy nhiên, có một sự khác biệt. is_a
là một hàm lấy một đối tượng làm tham số 1 và một chuỗi (biến, hằng hoặc bằng chữ) làm tham số 2. Vì vậy:
is_a($object, $string); // <- Only way to call it
instanceof
lấy một đối tượng làm tham số 1 và có thể lấy tên lớp (biến), thể hiện đối tượng (biến) hoặc định danh lớp (tên lớp được viết không có dấu ngoặc kép) làm tham số 2.
$object instanceof $string; // <- string class name
$object instanceof $otherObject; // <- object instance
$object instanceof ClassName; // <- identifier for the class
is_a
đánh giá cao?
$class = 'Foo'; var_dump($obj instanceof $class);
is_a
vs instanceof
toán tử là is_a
sẽ chấp nhận các biểu thức cho tham số thứ hai, trong khi instanceof sẽ không. Ví dụ is_a($object, 'Prefix_'.$name)
hoạt động trong khi $object instanceof 'Prefix_'.$name
không
is_a
không bao giờ nên bị từ chối ở nơi đầu tiên. Bây giờ đã muộn một chút để sửa nó. Vấn đề là instanceof
toán tử ném lỗi cú pháp trong PHP 4 và do is_a
không được dùng cùng lúc với toán tử được giới thiệu nên không thể viết mã cho cả PHP 4 và 5 mà không ném E_STRICT. Bạn thậm chí không thể làm được if (version_compare(PHP_VERSION, 5) >= 0) { /* use instanceof */ } else { /* use is_a */ }
vì nó vẫn gây ra lỗi cú pháp trong PHP 4.
Đây là kết quả hoạt động của is_a () và instanceof :
Test name Repeats Result Performance
instanceof 10000 0.028343 sec +0.00%
is_a() 10000 0.043927 sec -54.98%
Nguồn kiểm tra là đây .
php 7
không có sự khác biệt.
instanceof
có thể được sử dụng với các thể hiện đối tượng khác, tên lớp hoặc giao diện. Tôi không nghĩ rằng nó (Cập nhật: Xem https://gist.github.com/1455148 )is_a()
hoạt động với các giao diện (chỉ một chuỗi đại diện cho một tên lớp), nhưng sửa lại cho tôi nếu nó đúng.
Ví dụ từ 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'
đầu ra:
bool(true)
bool(true)
bool(false)
is_a
không hoạt động với các giao diện giống như instanceof
(tôi sẽ nói điều tương tự, nhưng tôi đã kiểm tra nó trước khi gửi, và nó thực sự hoạt động) ...
Liên quan đến câu trả lời của ChrisF, is_a()
không còn bị phản đối kể từ phiên bản PHP 5.3.0. Tôi thấy nó luôn an toàn hơn khi đi theo nguồn chính thức cho những thứ như thế này.
Liên quan đến câu hỏi của bạn, Daniel, tôi không thể nói về sự khác biệt về hiệu suất, nhưng một phần của câu hỏi sẽ dễ đọc và bạn thấy dễ làm việc hơn.
Ngoài ra, có một số cuộc thảo luận về sự nhầm lẫn xung quanh việc phủ định một instanceof
séc so với is_a()
. Ví dụ, đối với instanceof
bạn sẽ làm:
<?php
if( !($a instanceof A) ) { //... }
?>
so với sau đây cho is_a()
:
<?php
if( !is_a($a, 'A' ) { //... }
?>
hoặc là
<?php
if( is_a($a, 'A') === FALSE) { //... }
?>
Chỉnh sửa Có vẻ như ChrisF đã xóa câu trả lời của anh ấy, nhưng phần đầu tiên trong câu trả lời của tôi vẫn đứng vững.
Bên cạnh tốc độ, một sự khác biệt quan trọng khác là cách họ xử lý các trường hợp cạnh.
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.
Vì vậy, is_a () nêu bật các lỗi có thể xảy ra trong khi instanceof loại bỏ chúng.
Việc tối ưu hóa là tối thiểu. Và tối ưu hóa vi mô không bao giờ là một câu trả lời thực sự tốt, trước khả năng đọc, dễ hiểu và ổn định của mã.
(cá nhân tôi là ví dụ trước , nhưng sự lựa chọn là của bạn;))
Sự khác biệt chính là khả năng sử dụng tên lớp trực tiếp với instanceof
$ một ví dụ của MyClass
ngắn hơn
is_a ($ a, MyClass :: class)
(ok, nó không tầm thường.)
Màu sắc cú pháp giữa instanceof (cấu trúc ngôn ngữ) và is_a cũng hữu ích (đối với tôi). cho phép màu sắc chức năng để hoạt động lớn hơn. Và để sử dụng một lần trong if, instanceof dos không cần thêm dấu ngoặc đơn.
Lưu ý: Tất nhiên thay vì MyClass :: class, bạn có thể sử dụng chuỗi trực tiếp ngắn hơn:
is_a ($ a, 'MyClass')
Nhưng sử dụng chuỗi trực tiếp trong một mã không phải là một thực hành tốt .
Việc thu thập cú pháp tốt hơn và hữu ích hơn nếu bạn có thể tạo sự khác biệt giữa tên chuỗi đơn giản và tên lớp. Và nó dễ dàng hơn để thay đổi tên với tên lớp không đổi. Đặc biệt nếu bạn sử dụng không gian tên với bí danh.
Vì vậy, wy sử dụng is_a () ?
Đối với cùng một tù nhân: khả năng đọc và không thể phá hủy. (sự lựa chọn là của bạn) Đặc biệt khi sử dụng với ! hoặc các toán tử boolean khác: is_a có vẻ hợp lý hơn với dấu ngoặc đơn.
if ($ a AND (! is_a ($ a, MyClass :: class) HOẶC is_a ($ a, MyOtherClass :: class)))
dễ đọc hơn:
if ($ a AND (! ($ a instanceof MyClass) HOẶC ($ a intanceof MyOtherClass)))
Một lý do tốt khác là khi bạn cần sử dụng gọi lại trong các chức năng. (Như array_map ...) instanceof không phải là một chức năng, đó là một cấu trúc ngôn ngữ, vì vậy bạn không thể sử dụng nó như là gọi lại.
Trong trường hợp those, is_a có thể hữu ích
Tôi không thể nói về hiệu suất - Tôi chưa đo bất cứ điều gì - nhưng tùy thuộc vào những gì bạn đang cố gắng, có những hạn chế instanceof
. Kiểm tra câu hỏi của tôi, chỉ gần đây, về nó:
PHP 'instanceof' thất bại với hằng số lớp
Tôi đã kết thúc bằng cách sử dụng is_a
thay thế. Tôi thích cấu trúc instanceof
tốt hơn (tôi nghĩ nó đọc đẹp hơn) và sẽ tiếp tục sử dụng nó ở nơi tôi có thể.
Dưới đây là kết quả hiệu suất thu được từ đây :
instanceof
nhanh hơn.
Chức năng
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';
}
Lần (chạy 5000 lần mỗi lần)
0.00573397 // method_1(5)
0.01437402 // method_2(5)
0.00376201 // method_3(5)
Có một kịch bản chỉ is_a()
hoạt động và instanceof
sẽ thất bại.
instanceof
mong đợi một tên lớp theo nghĩa đen hoặc một biến là một đối tượng hoặc một chuỗi (với tên của một lớp) là đối số đúng của nó.
Nhưng nếu bạn muốn cung cấp chuỗi tên lớp từ một hàm gọi thì nó sẽ không hoạt động và dẫn đến lỗi cú pháp.
Tuy nhiên, kịch bản tương tự hoạt động tốt với is_a()
.
Thí dụ:
<?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()));
Điều này dựa trên PHP 7.2,14.