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.