Dans la perspective du langage de programmation, que signifie le sous-typage? J'ai entendu dire que "l'héritage n'est pas un sous-typage". Quelles sont alors les différences entre l'héritage et le sous-typage?
Dans la perspective du langage de programmation, que signifie le sous-typage? J'ai entendu dire que "l'héritage n'est pas un sous-typage". Quelles sont alors les différences entre l'héritage et le sous-typage?
Réponses:
[Je n'ai pas longuement réfléchi aux problèmes des systèmes de type orienté objet, mais je dirai ce que je sais pour lancer la discussion.]
Nous disons que est un sous-type de B si toutes les valeurs de type A peuvent être utilisées dans tous les contextes où des valeurs de type B sont attendues. Ou, pour le dire autrement, les valeurs de type A peuvent se "masquer" comme des valeurs de type B.
Si un tel masquage ne pose aucun problème avec la vérification de type, c'est-à-dire que le branchement de valeurs de type où des valeurs de type B sont nécessaires continue à taper la vérification, nous l'appelons "sous-typage structurel" . S'il ne pose aucun problème de comportement, c'est-à-dire qu'un tel bouchage ne modifie pas le comportement attendu, nous l'appelons alors "sous-typage comportemental" . (Le "comportement attendu" devra être formalisé séparément et de nombreuses notions de comportement sont possibles.)
Le sous-typage structurel n'assure pas le sous-typage comportemental car la structure d'un type peut correspondre pour des raisons accidentelles. Cependant, définir le comportement attendu n'est pas facile. Ainsi, de nombreux langages de programmation utilisent un point intermédiaire, où l'utilisateur doit déclarer quel type est un sous-type dont. C'est ce que l'on appelle le "sous-typage nominal" . Voir la question sur le sous-typage implicite vs explicitepour une discussion de cette question. L'idée est que le programmeur doit assurer le sous-typage comportemental pour tous les sous-types déclarés en utilisant sa propre ingéniosité. La langue ne peut offrir aucune aide. Cependant, tous les sous-types déclarés doivent être au moins des sous-types structurels. Sinon, le programme ne parviendrait pas à taper check. La langue peut aider à garantir cela. (Certains langages de programmation ne disposent pas de systèmes de type suffisamment bons pour garantir cela au moment de la compilation. Si tel est le cas, l'échec de type serait détecté au moment de l'exécution, ou des résultats erronés pourraient être produits. De tels trous de type ne sont évidemment pas souhaitables.)
Quand on définit des sous-classes dans des programmes orientés objet, on ajoute généralement des champs (ou méthodes) publiquement visibles. Dans la plupart des langages de programmation, ces sous-classes sont considérées comme des sous - types nominaux . La question est de savoir si ce sont également des sous-types structurels . S'ils ne le sont pas, c'est-à-dire que le langage de programmation permet de déclarer des sous-types nominaux qui ne sont pas des sous-types structurels, alors il y aurait des trous de type dans le langage de programmation.
Dans les cas simples, l'ajout de champs fonctionne correctement. Le type de la superclasse attend moins de champs que le type de la sous-classe. Donc, si vous branchez une instance d'une sous-classe où une instance de la sueprclass est attendue, le programme ignorera simplement les champs supplémentaires fournis et rien ne va mal.
Cependant, si la superclasse ou la sous-classe possède des méthodes qui acceptent des arguments du même type que lui-même ou renvoient des résultats du même type que lui-même, des problèmes se posent. Le type d'interface de la sous-classe n'est alors pas un sous-type structurel de celui de la superclasse. Les langages de programmation de type sûr largement utilisés tels que Java n'autorisent pas de telles sous-classes. Ainsi, ils restreignent la langue pour obtenir la sécurité des types. Le langage de programmation Eiffel aurait sacrifié la sécurité de type pour obtenir de la flexibilité à la place. Si l'on conçoit un système de type solide qui conserve sa flexibilité, il faut renoncer au principe selon lequel les sous-classes donnent naissance à des sous-types. D'où le titre de l'article "L'hérédité n'est pas un sous-typage". Les auteurs proposent une notion différente de sous-typage d'ordre supérieur qui fonctionne à la place. Kim Bruce a également une proposition étroitement liée appelée "appariement" qui produit le même effet. Voir cette présentation . Un document de position d'Andrew Black est également utile .
La communauté sémantique est probablement en faute d'avoir largement ignoré le problème. Nous l'avons traditionnellement considéré comme un problème pratique d'ingénierie des systèmes de types qui présente peu d'intérêt théorique. Si ce n'est pas le cas et qu'il y a effectivement du travail sémantique dans le domaine, j'espère que les autres personnes les mentionneront.