Un objet est créé à partir d'une classe c
avec la syntaxe new
,
où c est la classe génératrice et
sont les (éventuels) paramètres
d'initialisation. L'objet créé est dit instance de la classe c
ou simplement de classe c.
let c1 = new cell;; val c1 : cell = <obj> let p1 = new point(0,1);; val p1 : point = <obj>
L'objet c1 est un instance de cell
et p1 est une instance de point
avec (0,1) en coordonnées initiales. Chaque nouvel objet
contient toutes les variables et les méthodes
de sa classe génératrice. Cet ensemble de variables et
méthodes est couramment nommé attributs de la
classe (ou de l'objet).
Le comportément lors de la création d'un objet peut être expliqué de la manière suivante2 : new c alloue un enregistrement d'attributs qui contient les valeurs initiales des variables, et le code des méthodes de c, et retourne en résultat un pointeur vers celui-ci. Des exécutions différentes de new produisent des objets différents, c.a.d., des pointeurs vers des enregistrements d'attributs différents. Ainsi, bien que p2 plus bas soit une instance de point initialisée aux mêmes valeurs que p1, il s'agit de deux objets différents.
let p2 = new point(0,1);; val p2 : point = <obj> p1 = p2;; - : bool = false
De plus, les variables de tous les objets d'une classe évoluent
séparemment: chaque objet possède des variables séparées
(ce qu'on nomme parfois, l'état de l'objet).
En Ocaml, bien que l'enregistrement d'attributs d'un objet
contienne éffectivement tous les attributs de sa classe,
seules les méthodes
sont visibles en dehors de l'objet. Ni les variables,
et encore moins les valeurs des paramètres ne peuvent être extraites
de l'objet (pour plus des détails, voir partie suivante).
Ce masquage des variables (qui revient à protéger l'accèss aux données de l'objet), se reflète dans le type inféré pour un objet: il spécifie seulement les méthodes de sa classe génératrice. Il faut donc distinguer entre le type ou interface d'une classe, et le type des objets crées à partir de celle-ci. Dans la première sont spécifiés tous les attributs de la classe; dans le deuxième, seulement les méthodes. Prenons l'exemple de la classe cell. Son interface est
class cell : object val mutable x : int method get : int method set : int -> unit end
Un objet de cette classe, a pour type une version de l'interface
restreinte aux spécifications des méthodes. Si l'on
note Type_Instance_de(c) le type des objets
de classe c, alors le type de c1 est donné par
c1 : Type_Instance_de(cell)
En Ocaml, ce type correspond à la spécification
Type_Instance_de(cell) =
< get : int; set : int -> unit >
mais, dans la syntaxe Ocaml, Type_Instance_de(cell) est noté cell. Ceci explique le message
let c1 = new cell;; val c1 : cell = <obj>
qu'il faut comprendre
val c1 : < get : int; set : int -> unit > = <obj>