Nous avons vu qu'une sous-classes n'est pas toujours un sous-type de
sa super-classe. Les méthodes binaires sont un exemple important,
car très courant et nécessaire en programmation, où l'identification
entre les notions de sous-classe et de sous-type est impossible.
Pourtant, la plupart des langages OO typés statiquement imposent aux
sous-classes de produire de sous-types, même dans le cas de méthodes
binaires. Une restriction dans ce sens est d'imposer que les types des
méthodes ne changent pas lors de l'héritage. Quelques langages dans
ce cas sont:
,
Object Pascal et Modula. Dans ces langages,
on ne pourra pas écrire l'équivalent de la classe colorpoint,
ou de la classe vegetarien,
avec le typage donné plus haut.
D'autres langages comme Eiffel et O2, admettent la spécialisation des types
des méthodes telles que dans colorpoint. De plus, en
Eiffel toute sous-classe est considerée comme sous-type de sa super
classe. Du coup, les fonction comme breakit sont bien typés,
même lors d'un appel à un objet de type colorpoint, et
bien sûr, des erreurs peuvent se produire à l'exécution. Clairement,
le système de typage d'Eiffel n'est pas sûr. Les versions plus récentes
de ces langages insèrent des tests dynamiques dans les programmes.
En Java, le problème est contourné en affaiblissant
les règles de typage. Il suffit d'interdire le type de self
d'apparaître dans les types des méthodes. Par exemple, la
méthode d'égalité dans point aura le type
point -> bool et gardera ce type dans la classe des
points colorés après héritage. Cet affaiblissement force
l'utilisateur à réaliser des coercions explicites (qui peuvent
échouer) s'il veut par exemple, comparer deux points colorés.
La validité des coercions pouvant être vérifiés pendant
le typage, leur échec est prévisible et le système de typage
associé est donc sûr. Cependant, les programmes avec méthodes binaires
sont plus difficiles à écrire avec ces restrictions.
En Ocaml, le parti pris est différent. La spécialisation co-variante
du types des méthodes, comme dans les classes
binaires, sont jugées trop importantes
pour être exclues des programmes OO. Du coup, il est impossible de garantir
qu'une sous-classe soit sous-type de sa super-classe, mais on revanche
on peut assurer qu'elles sont en relation d'instantiation polymorphe.
Ce qui est suffisant pour réaliser des opérations programmées
par ``spécialisation co-variante''.
Par exemple, les classes point et colorpoint avec méthodes binaires d'égalité ont les types suivants en Ocaml:
mais, le type de equal dans colorpoint n'est pas
un sous-type de celui dans point: il est
une instance polymorphe de celui-ci. Pour s'en rendre
compte, il suffit de substituer dans le le type des
points
par
et
par
(getcolor : string).
L'instantiation polymorphe est plus faible que le sous-typage, mais il est
suffisant pour écrire la plupart des programmes. Il permet d'assurer
qu'un objet possède les méthodes attendues. De plus, l'instantiation
est une relation co-variante: elle change les types
(par specialisation) de même manière que les types des classes
se spécialisent par héritage.