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.[1] 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. [2]

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 (identical), or unrelated (incompatible)—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 (see: Subtyping § Subsumption).

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 (a child of) the type of the target variable (therefore, the parent), downcasting is possible.

Some languages, such as OCaml, disallow downcasting.[3]

Examples

edit

Java

edit
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++

edit
// 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, 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

edit

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.

Considerations

edit

A popular example of a badly considered design is containers of top types,[citation needed] like the Java containers before Java generics were launched, which requires downcasting of the contained objects so that they can be utilised again.

See also

edit

References

edit
  1. ^ TylerMSFT (2021-08-03). "How to: Use safe_cast in C++/CLI". learn.microsoft.com. Retrieved 2023-12-01.
  2. ^ Liang, Y. Daniel (2015). Introduction to Java Programming Comprehensive Version (10th ed.). Pearson. p. 427. ISBN 978-0-13-376131-3.
  3. ^ 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.
edit

📚 Artikel Terkait di Wikipedia

The Demon Downcast

The Demon Downcast (Russian: Демон поверженный) is a piece by the Russian painter Mikhail Vrubel, created around 1901–1902. The painting was made on canvas

Code smell

intended to be deployed in different regions.[self-published source] Downcasting a type cast which breaks the abstraction model; the abstraction may have

Type system

programming language features cannot be checked statically, such as downcasting. Thus, many languages will have both static and dynamic type checking;

Downcast (app)

"Downcast on the Mac App Store". apps.apple.com. Retrieved 2021-04-04. "Downcast on the App Store". apps.apple.com. Retrieved 2021-04-04. "Downcast (for

Any type

universal type but the unit type. In C++, downcasting from void* cannot be done in a safe way, where failed downcasts are detected by the language runtime

British Raj

Mahatma Gandhi (seated in carriage, on the right, eyes downcast, with black flat-top hat) receiving a big welcome in Karachi in 1916 after his return to

Trust, but verify

phrase has been used to describe the implementation of downcasting: the compiler trusts that the downcast term will be of the desired type, but this assumption

Type conversion

that hacked variable as the new data type for that specific operation. Downcasting Run-time type information § C++ – dynamic cast and Java cast Truth value