Downcasting
In class-based programming, downcasting, or type refinement, is the act of casting a base or parent class reference, to a more restricted derived class reference. This is only allowable if the object is already an instance of the derived class, and so this conversion is inherently fallible. In contrast upcasting, explicitly treating an object as if it's an instance of one of its superclasses, is always possible.
In many environments, type introspection can be used to obtain the type of an object instance at runtime, and then use this result to explicitly evaluate its type compatibility with another type. The possible results of comparing polymorphic types—besides them being equivalent, or unrelated —include two additional cases: namely, where the first type is derived from the second, and then the same thing but swapped the other way around.
With this information, a program can test, before performing an operation such as storing an object into a typed variable, whether that operation is type safe, or whether it would result in an error. If the type of the runtime instance is derived from the type of the target variable, downcasting is possible.
Some languages, such as OCaml, disallow downcasting.
Examples
Java
public class Fruit // parent class
public class Apple extends Fruit // child class
public static void main
C++
// Parent class:
class Fruit ;
// Child class:
class Apple : public Fruit ;
int main
Uses
Downcasting is useful when the type of the value referenced by the Parent variable is known and often is used when passing a value as a parameter. In the below example, the method objectToString takes an Object parameter which is assumed to be of type String.public static String objectToString
public static void main
In this approach, downcasting prevents the compiler from detecting a possible error and instead causes a run-time error.
Downcasting myObject to String was not possible at compile time because there are times that myObject is String type, so only at run time can we figure out whether the parameter passed in is logical. While we could also convert myObject to a compile-time String using the universal java.lang.Object.toString, this would risk calling the default implementation of toString where it was unhelpful or insecure, and exception handling could not prevent this.
In C++, run-time type checking is implemented through dynamic_cast. Compile-time downcasting is implemented by static_cast, but this operation performs no type check. If it is used improperly, it could produce undefined behavior.