Author: Christian.Queinnec@lip6.fr

## Langages à Objet : comparaison avec Java

Bien qu'Objective CAML soit issu du monde fonctionnel, il est nécessaire de comparer son extension objet à un représentant important des langages à objets. Nous choisissons le langage Java qui bien que proche du point de vue de son implantation, diffère fortement par son modèle objet et par son système de types.
Le langage Java est un langage à objets développé par la société SUN. Le site principal d'accès au langage est le suivant :

### Lien

http://java.sun.com

### Principales caractéristiques

Le langage Java est un langage à classes. L'héritage est simple et permet de redéfinir ou de surcharger des méthodes héritées. Le typage est statique. Une classe héritée est en relation de sous-typage avec sa classe ancêtre.
Java ne possède pas de classe paramétrée. On obtient deux types de polymorphisme : ad hoc pour la surcharge et d'inclusion pour la redéfinition.
Il est multi-threading et permet de développer des applications réparties soit en utilisant les sockets soit en invoquant une méthode sur des objets distants (Remote Method Invocation).
Les principes de son implantation sont proches de celle d'Objective CAML. Un programme Java est compilé vers une machine abstraite (JVM). Le chargement du code est dynamique. Le code produit est indépendant des architectures machines en étant évalué par un interprète de la machine virtuelle. Les types de données de base sont spécifiés de sorte à garantir une même représentation sur toutes les architectures. La bibliothèque d'exécution est munie d'un GC.
Java possède d'importantes bibliothèques de classes (environ 600 avec le JDK auxquelles s'ajoutent les nombreux développements indépendants). Les principales bibliothèques concernent les interfaces graphiques et les opérations d'entrées-sorties intégrant la communication entre machines.

### Différences avec Objective CAML

Les principales différences entre Java et Objective CAML tiennent à leur système de type, à la redéfinition et à la surcharge des méthodes. La redéfinition d'une méthode héritée doit utiliser des paramètres exactement de même type. La surcharge d'une méthode permet d'aiguiller le choix de la méthode à employer selon les types des paramètres d'appel. Dans l'exemple suivant la classe `B` hérite de la classe `A`. La classe `B` redéfinit la première version de la méthode `to_string`, mais surcharge la deuxième version. De même la méthode `eq` est surchargée car le type du paramètre (ici `B`) n'est pas égal au type du paramètre de la méthode héritée (ici `A`). Au final la classe `B` possède deux méthodes `eq` et deux méthodes `to_string`.

    class A {
      boolean eq (A o) {  return true;}
      String to_string (int n ) { }
    }

    class B extends A {
      boolean eq (B o) {  return true;}
      String to_string (int n ) { }
      String to_string (float x, float y)
    }

Bien que la liaison soit retardée, la résolution de la surcharge, c'est-à-dire la détermination du type de la méthode à utiliser, est effectuée à la compilation.
La deuxième différence importante provient de la possibilité de forcer le type d'un objet comme on le ferait en C. Dans l'exemple suivant, on définit deux objets `a` et `b`, respectivement de classe `A` et `B`. On déclare ensuite trois variables `c`, `d` et `e` en posant une contrainte de type sur les valeurs affectées.

    {
      A a = new A ();
      B b = new B ();
      A c = (A) b;
      B d = (B) c;
      B e = (B) a;
    }

Comme le type de `b` est sous-type du type de `a`, alors l'affectation de `b` à `c` est acceptée. Dans ce cas la contrainte de type peut être omise. Par contre les deux contraintes suivantes nécessitent d'effectuer un test dynamique de type pour garantir que les valeurs dans `c` et dans `a` correspondent en fait à des objets de la classe `B`. Dans ce programme cela est vrai pour `c`, mais faux pour `a`. Ce dernier cas déclenche alors une exception. Bien que cela soit pratique, en particulier pour les interfaces graphiques, ces contraintes de type peuvent entraîner des déclenchements d'exceptions à l'exécution pour l'utilisation de types erronés. En cela Java est un langage typé en partie statiquement et en partie dynamiquement. De plus l'absence de classe paramétrée oblige bien souvent à utiliser ce trait pour écrire des classes génériques.