Le typage statique est une technique utilisée dans certains langages de programmation impératifs (C++, Java, Pascal, par exemple) pour associer à un symbole dénotant une variable le type de la valeur dénotée par la variable ; et dans certains langages de programmation fonctionnels (ML, Objective Caml, Haskell, etc.) pour associer à une fonction (un calcul) le type de son paramètre et le type de la valeur calculée.
Une telle association présente les bénéfices potentiels suivants :
(déplacer vers nouvel article : le problème de la covariance/contravariance)
Les langages à objets en particulier peuvent tirer parti du typage statique, afin de détecter avant l'exécution des erreurs de types (comme par exemple la tentative d'additionner un entier avec une chaîne de caractères). Toutefois, la sûreté du typage et la programmation orientée objet sont parfois en contradiction, parce que le typage sûr va à l'encontre de la modélisation « naturelle » du problème à résoudre avec l'approche objet (redéfinition contravariante du type des paramètres des méthodes pour la sûreté du typage vs. redéfinition covariante dans l'approche objet).
Pour éclaircir la dernière phrase, nous travaillons sur un exemple. Considérons en Java l'extrait de code suivant :
Graphe mon_graphe = new Graphe (); Nœud n1, n2; n1 = new Nœud (); n2 = new Nœud (); Arête a = new Arête (n1, n2); mon_graphe.ajout_nœud (n1); mon_graphe.ajout_nœud (n2); mon_graphe.ajout_arête (a);
Quatre objets sont déclarés et instanciés, précédés de leur type (respectivement Graphe, Nœud, Arête). Si le programmeur essaye d'instancier mon_graphe avec le type Nœud, le compilateur le lui interdit car mon_graphe a été déclaré comme étant de type Graphe (contrôle sur le type de retour).
De même, si la méthode ajout_nœud () de la classe Graphe a été définie comme ceci :
boolean ajout_nœud (Nœud n) { ... }
c'est-à-dire en spécifiant le type du paramètre reçu, le compilateur saura détecter une erreur d'appel (par exemple 'mon_graphe.ajout_nœud (a)') - (contrôle sur le type des paramètres).
Des langages comme Java et C++ ont tranché en faveur de l'invariance des types de retour et des paramètres de méthodes bien que dans ces deux langages, les types de retour puissent être covariants.
Les besoins de la modélisation (covariance du type des paramètres) entraînent des astuces plus ou moins contestables pour la simuler dans ces langages : il faut combiner des opérateurs de *coercition descendante* (downcast) et la *surcharge statique* de méthodes pour y arriver.
Le langage de programmation Eiffel est le seul à admettre la redéfinition covariante du type des paramètres.
Dans *tous* les cas, le programmeur doit anticiper des erreurs de type à l'exécution, comme dans les langages à typage dynamique. En résumé, il faut admettre que « les erreurs de type sont dans la nature ». Par exemple, considérons :
Ce typage est (a priori) incorrect, et le compilateur refusera le programme car manifestement herbe <: nourriture (<: « est un sous-type de »). En pratique rien n'empêche qu'une instance de « Pâté d'alouettes » ne soit donné en paramètre à une instance de Vache. Corrigeons :
Le typage est donc « sûr », car nourriture <: tout. Donc à l'exécution, la vache peut recevoir des farines animales. La maladie de la vache folle est une erreur de type, garantie par la sûreté du typage...