Downcasting

In object-oriented programming, downcasting or type refinement is the act of casting a reference of a base class to one of its derived classes.

In many programming languages, it is possible to check through RTTI whether the type of the referenced object is indeed the one being cast to or a derived type of it, and thus issue an error if it is not the case.

In other words, when a variable of the base class (parent class) has a value of the derived class (child class), downcasting is possible.

For example in Java:

public class Parent{}
public class Child extends Parent(){}
 
public static void main(String args[]){
    Parent parent = new Child();              // Parent is parent class of Child, parent variable holding value of type Child
    Child child = (Child)parent;              // This is possible since parent object is currently holding value of Child class
}

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 String objectToString(Object myObject){
    return (String)myObject; //This will only work when the myObject currently holding value is string.
}
 
public static void main(String args[]){
    String result = objectToString("My String"); //This will work since we passed in String, so myObject has value of String.
    Object iFail = new Object();
    result = objectToString(iFail);              //This will fail since we passed in Object which does not have value of String.
}

In this approach, downcasting prevents the compiler from detecting a possible error and instead causes a run-time error. Downcasting myObject to String ('(String)myObject') was possible in compile time because there are times that myObject is String type, so only in 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.

Useful source introducing concept of downcasting: "Upcasting, downcasting" by Sinipull

Criticism

Many people advocate avoiding downcasting, since according to the LSP, an OOP design that requires it is flawed. Some languages, such as OCaml, disallow downcasting altogether.[citation needed]

A popular example of a badly considered design is containers of top types, like the Java containers before Java generics were introduced, which requires downcasting of the contained objects so that they can be used again.

↑Jump back a section

Read in another language

This page is available in 2 languages

Last modified on 17 March 2013, at 04:01