Downcasting - Downcasting

Dans la programmation basée sur les classes , le downcasting ou le raffinement de type est l'acte de transtyper une référence d'une classe de base vers l'une de ses classes dérivées.

Dans de nombreux langages de programmation , il est possible de vérifier par l' introspection de type pour déterminer si le type de l'objet référencé est bien celui en cours de conversion ou un type dérivé de celui-ci, et ainsi émettre une erreur si ce n'est pas le cas.

En d'autres termes, lorsqu'une variable de la classe de base (classe parente ) a une valeur de la classe dérivée ( classe enfant ), le downcasting est possible.

Exemples

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);
}

Les usages

Le downcasting est utile lorsque le type de la valeur référencée par la variable Parent est connu et est souvent utilisé lors du passage d'une valeur en tant que paramètre. Dans l'exemple ci-dessous, la méthode objectToString prend un paramètre Object qui est supposé être de 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);
}

Dans cette approche, le downcasting empêche le compilateur de détecter une erreur possible et provoque à la place une erreur d'exécution. Downcasting myObject to String ('(String) myObject') n'était pas possible au moment de la compilation car il y a des moments où myObject est de type String, donc ce n'est qu'au moment de l'exécution que nous pouvons déterminer si le paramètre passé est logique. Bien que nous puissions également convertir myObject en String au moment de la compilation à l'aide de la fonction universelle java.lang.Object.toString (), cela risquerait d'appeler l'implémentation par défaut de toString () là où elle était inutile ou non sécurisée, et la gestion des exceptions ne pourrait pas empêcher cela .

En C ++, la vérification de type à l'exécution est implémentée via dynamic_cast . Le downcasting à la compilation est implémenté par static_cast , mais cette opération n'effectue aucune vérification de type. S'il n'est pas utilisé correctement, il peut produire un comportement indéfini.

Critique

Certaines langues, telles que OCaml , interdisent complètement la diffusion descendante.

Les conteneurs de types supérieurs , comme les conteneurs Java avant l' introduction des génériques Java, sont un exemple courant de conception mal envisagée , ce qui nécessite un abaissement des objets contenus afin qu'ils puissent être réutilisés.

Voir également

Les références

Liens externes