Downcasting

In class-based 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 type introspection to determine 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.

Examples

Java

public class Fruit{}  // parent class
public class Apple extends Fruit{}  // child class

public static void main(String args[]) {
    // The following is an implicit upcast:
    Fruit parent = new Apple();
    // The following is a downcast. Here, it works since the variable `parent` is
    // holding an instance of Apple:
    Apple child = (Apple)parent;
}

C++

// Parent class:
class Fruit {
 public:
  // Must be polymorphic to use runtime-checked dynamic-cast.
  virtual ~Fruit() = default;
};

// Child class:
class Apple : public Fruit {};

int main(int argc, const char** argv) {
  // The following is an implicit upcast:
  Fruit* parent = new Apple();
  // The following is a downcast. Here, it works since the variable `parent` is
  // holding an instance of Apple:
  Apple* child = dynamic_cast<Apple*>(parent);

  delete parent;
}

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(Object myObject) {
    // This will only work when the myObject currently holding value is string.
    return (String)myObject;
}

public static void main(String args[]) {
    // This will work since we passed in String, so myObject has value of String.
    String result = objectToString("My String");
    Object iFail = new Object();
    // This will fail since we passed in Object which does not have value of String.
    result = objectToString(iFail);
}

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 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.

Criticism

Some languages, such as OCaml, disallow downcasting altogether.[1]

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.

gollark: I see.
gollark: Domains is less information than full paths, how exactly are you meant to know when to stop receiving a document with this (closing the connection‽), and there's an ESNI thing in the works.
gollark: ALL protocols are to support reasonable confidentiality.
gollark: Maybe, but it can have POST bodies.
gollark: - gpg is isomorphic to cryoapioform - it is already too late, as I just interfaced this with a JS engine and some HTML layouting stuff and am accessing my email through this; for now, I am using an SSH tunnel, but this is uncool, so security *is* required - additionally, normalizing protection of exactly which content you visit from eavesdroppers is good- it doesn't even have a Content-Length field- but I need to store arbitrarily large indices into metagollarious ultraspace

See also

  • Subtype polymorphism

References

  1. Vouillon, Jérôme; Rémy, Didier; Garrigue, Jacques (September 12, 2013). "Objects in OCaml". The OCaml system release 4.01 : Documentation and user's manual.
This article is issued from Wikipedia. The text is licensed under Creative Commons - Attribution - Sharealike. Additional terms may apply for the media files.