I'm curious as to how instance testing (instanceof/is/using dynamic_cast in c++) works
In Java, ogni oggetto memorizza un puntatore al suo tipo. Ogni tipo conosce i suoi tipi principali, quindi è semplice enumerare tutti i tipi di antenati. x instanceof T
se incontriamo T
durante la ricerca.
Analogamente, in C ++, gli oggetti delle classi con metodi virtuali memorizzeranno un puntatore a type_info
:
Every virtual table shall contain one entry that is a pointer to an object derived from std::type_info
. (source)
(Questo è tuttavia specifico per gcc; non conosco altri compilatori.)
Also, it's been drilled into my head that using instance testing is a mark of bad design. Why exactly is this? When is that applicable, instanceof should still be used in methods like .equals() and such right?
L'idea è che, quando possibile, è preferibile utilizzare il polimorfismo piuttosto che controllare sottotipi specifici. Tende ad essere più elegante e non c'è alcuna possibilità di dimenticare di aggiornare i controlli dei sottotipi quando aggiungiamo un nuovo sottotipo.
Esempio totalmente forzato: diciamo che abbiamo Animal
con sottotipi Lion
, ecc. Se vogliamo verificare se Animal a
è un carnivoro, potremmo scrivere a instanceof Lion || a instanceof Bear || ...
, ma sarebbe più pulito e più sicuro da aggiungere un abstract boolean isCarnivore();
in Animal
.
Ma sono d'accordo, instanceof
è ancora appropriato in equals
poiché l'API ci obbliga a gestire Object
s.
When you have mutliple catch statements, how does that work? Is that instance testing or is it just resolved during compilation where each thrown exception would go to?
In Java, non è possibile per un compilatore precompilare il percorso di ciascuna eccezione perché è possibile caricare nuove classi di eccezioni in fase di runtime.
Il compilatore genera una "tabella di eccezioni" per ogni blocco try / catch, in cui una riga nella tabella contiene un tipo di eccezione e un offset pc
che dovrebbe essere applicato se si verifica tale eccezione. Ma se dichiari catch (IOException)
, la tabella delle eccezioni conterrà solo IOException
, non sottoclassi come EOFException
. Un controllo instanceof
-like deve essere eseguito in fase di esecuzione per verificare se un'eccezione generata è IOException
.