For curiosity purposes as well as understanding what they entail in a program, I’m curious as to how instance testing (instanceof
/is
/using dynamic_cast
in c++) works. I’ve tried to google it (particularly for java) but the only pages that come up are tutorials on how to use the operator.
How do the implementations vary across those langauges? How do they treat classes with identical signatures?
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?
I was also thinking of this in the context of exception handling, again particularly in Java. 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?
6
I’m curious as to how instance testing (instanceof/is/using dynamic_cast in c++) works
In Java, each object stores a pointer to its type. Each type knows its parent types, so it’s straightforward to enumerate all ancestor types. x instanceof T
iff we encounter T
during the search.
Similarly, in C++, objects of classes with virtual methods will store a pointer to a type_info
:
Every virtual table shall contain one entry that is a pointer to an object derived from
std::type_info
. (source)
(This is gcc-specific though; I don’t know about other compilers.)
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?
The idea is that, when possible, it’s preferable to use polymorphism rather than checking for specific subtypes. It tends to be more elegant, and there’s no possibility of forgetting to update our subtype checks when we add a new subtype.
Totally contrived example: say we have Animal
with subtypes Lion
, etc. If we want to check if Animal a
is a carnivore, we could write a instanceof Lion || a instanceof Bear || ...
, but it would be cleaner and safer to add an abstract boolean isCarnivore();
in Animal
.
But I agree, instanceof
is still appropriate in equals
since the API forces us to deal with 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, it’s not possible for a compiler to precompute each exception’s path because new exception classes could be loaded at runtime.
The compiler does generate an “exception table” for each try/catch block, where a row in the table contains an exception type and a pc
offset which should be applied if that exception is encountered. But if you declare catch (IOException)
, the exception table will only contain IOException
, not subclasses like EOFException
. An instanceof
-like check has to be done at runtime to check if a thrown exception is an IOException
.
2