Inheritance denotes an is-a
relationship. Any object of IfTest
is-an If1
. However, a reference of type If1
does not necessarily refer to an object of type IfTest
.
In a textbook scenario, any Dog
is an Animal
but any Animal
is not a Dog
(it might be a zebra, elephant, deer, etc).
Casting takes the form:
A a = (B) c;
There are 2 steps involved:
- You have any object
c
that is cast to type B
.
- That instance of
B
is then assigned to variable a
(where A
is a type that must be either equal to B
or a super class of B
for the compiler to be happy and for no ClassCastExceptions
to occur at runtime.
Continuing the animal metaphor, you are casting Dog
to an Animal
in step 1, but then trying to assign that instance of an Animal
to a variable of type Dog
, which the compiler knows is not allowed.
The following would work because it casts IfTest
to If1
and then assigning that If1
to IfTest
.
if1 var3 = (if1) new ifTest();
EDIT As Lew points out in his comment below, this is what is referred to as a widening cast (because it goes from a specific type to a more generic, "wider" type. In this instance, the cast is not necessary because the compiler knows all references to objects of type IfTest
by definition are also If1
.
A more practical example would be if you had a reference to the interface and wanted to cast it to a IfTest
. In this case, it's a "narrowing" cast because you're going from the generic type to a more specific, "narrower" type.
if1 var1 = (if1) new ifTest();
if (var1 instanceOf ifTest) {
ifTest var2 = (ifTest) var1;
}
Note the use of the instanceof
to to ensure that var1
is in fact an instance of IfTest
. While we know it is, in a real-world application If1
might have multiple subtypes so this will not always be true. The check prevents the cast from throwing a run-time ClassCassException
.
TLDR: The important thing to know is what is inside the parenthesis must be a type the compiler knows can be assigned to the variable being assigned to.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…