instanceof
Scopri come l'operatore PHP instanceof verifica se un oggetto appartiene a una classe, a una classe padre o a un'interfaccia implementata, con esempi.
L'operatore PHP instanceof
instanceof è un operatore PHP per la verifica dei tipi. Restituisce un valore boolean (true o false) che indica se un oggetto appartiene a una determinata classe — o, più utilmente, se appartiene a una classe padre nella catena di ereditarietà oppure implementa una determinata interfaccia.
Questa pagina illustra la sintassi, il comportamento di instanceof con l'ereditarietà e le interfacce, come usarlo con il nome di una classe memorizzato in una variabile, i casi limite che sorprendono (non-oggetti, null, nomi di classe sconosciuti) e quando conviene usarlo rispetto a un'alternativa più pulita.
Se le classi e gli oggetti sono nuovi per te, leggi prima PHP Classes and Objects.
Sintassi
$object instanceof ClassNameL'espressione restituisce true quando $object è un'istanza di ClassName, di una qualsiasi classe che estende ClassName, oppure di una qualsiasi classe che implementa ClassName (quando ClassName è un'interfaccia). Altrimenti restituisce false. Si noti che non esiste una sintassi a chiamata di metodo — instanceof è un operatore, come ===, non una funzione.
Una verifica di base
<?php
class MyClass {}
class MyOtherClass {}
$object = new MyClass();
if ($object instanceof MyClass) {
echo "The object is an instance of MyClass.";
} else {
echo "The object is not an instance of MyClass.";
}
// Output: The object is an instance of MyClass.
var_dump($object instanceof MyOtherClass);
// Output: bool(false)$object è stato creato da MyClass, quindi il primo controllo è true. Non ha nulla a che fare con MyOtherClass, quindi quel controllo è false. Le due classi non sono correlate, anche se sembrano simili.
instanceof e l'ereditarietà
Il vero valore di instanceof è che percorre l'intera catena di ereditarietà. Un oggetto figlio è un'istanza della sua classe padre, quindi il controllo ha successo per ogni antenato.
<?php
class Fruit {}
class Apple extends Fruit {}
class Banana extends Fruit {}
$apple = new Apple();
var_dump($apple instanceof Apple); // bool(true) — its own class
var_dump($apple instanceof Fruit); // bool(true) — its parent class
var_dump($apple instanceof Banana); // bool(false) — a sibling class$apple supera il controllo Fruit perché Apple estende Fruit. Fallisce il controllo Banana perché Apple e Banana sono classi sorelle — nessuna eredita dall'altra. Scopri di più in PHP Inheritance.
instanceof e le interfacce
instanceof viene usato più comunemente con le interfacce. Poiché qualsiasi classe che implementa un'interfaccia conta come sua istanza, è possibile verificare una capacità senza preoccuparsi della classe concreta.
<?php
interface Drawable {
public function draw(): string;
}
class Circle implements Drawable {
public function draw(): string { return "○"; }
}
class Square implements Drawable {
public function draw(): string { return "□"; }
}
$shapes = [new Circle(), new Square(), "not a shape"];
foreach ($shapes as $shape) {
if ($shape instanceof Drawable) {
echo $shape->draw();
}
}
// Output: ○□La stringa "not a shape" viene ignorata perché non è un Drawable. Questo è il caso d'uso quotidiano: filtrare una lista mista per ottenere solo gli oggetti che supportano il comportamento necessario. Consulta PHP Interfaces per il quadro completo.
Usare un nome di classe da una variabile
Il lato destro può essere una variabile stringa contenente il nome di una classe o interfaccia. Questo è utile quando il tipo viene determinato a runtime.
<?php
class Fruit {}
class Apple extends Fruit {}
$apple = new Apple();
$type = 'Fruit';
var_dump($apple instanceof $type); // bool(true)È anche possibile confrontare due oggetti — $a instanceof $b funziona quando $b è un oggetto, verificando se $a è un'istanza della classe di $b.
Casi limite e insidie
instanceof non genera mai eccezioni né avvisi. Quando l'operando sinistro non è un oggetto, restituisce semplicemente false.
<?php
class Fruit {}
var_dump(null instanceof Fruit); // bool(false)
var_dump("Fruit" instanceof Fruit); // bool(false) — a string is not an object
var_dump(42 instanceof Fruit); // bool(false)Questo rende instanceof sicuro da usare come guardia prima di chiamare un metodo, senza dover verificare prima is_object(). Se hai bisogno solo di sapere se un valore è un oggetto qualsiasi (di qualsiasi classe), usa invece is_object().
Un punto sottile: se si passa come stringa letterale sul lato destro un nome di classe che non esiste, PHP non esegue l'autoload né genera un errore — restituisce semplicemente false. Un errore di battitura nel nome della classe fallisce silenziosamente. Preferisci il nome di classe nudo ($x instanceof Fruit) a una stringa quando possibile, così il parser lo valida.
Quando usare instanceof — e quando no
Usa instanceof quando hai davvero un valore di cui non puoi garantire il tipo: dati da json_decode, una raccolta mista, un plugin restituito da codice utente, oppure un blocco catch che restringe un'eccezione.
<?php
try {
throw new InvalidArgumentException("bad input");
} catch (Exception $e) {
if ($e instanceof InvalidArgumentException) {
echo "Caught an argument error: " . $e->getMessage();
}
}
// Output: Caught an argument error: bad inputEvita di disseminare controlli instanceof nel codice per ramificare in base al tipo — le lunghe catene if ($x instanceof A) … elseif ($x instanceof B) significano di solito che un metodo dovrebbe essere definito su ciascuna classe e chiamato polimorficamente. Ricorri a instanceof per proteggere un'operazione, non per sostituire l'ereditarietà.
Riepilogo
$object instanceof ClassNamerestituiscetruese l'oggetto è un'istanza della classe, di una sottoclasse o di un'interfaccia implementata.- Percorre l'intera catena di ereditarietà e fa corrispondere le interfacce — questo è ciò che lo rende potente.
- Restituisce
false(mai un errore) pernull, scalari e altri non-oggetti, quindi è sicuro come guardia. - Un nome di classe inesistente passato come stringa restituisce
falsesilenziosamente; preferisci il nome di classe nudo. - Usalo per verificare il tipo di un valore sconosciuto prima di agire su di esso, non come sostituto del polimorfismo.