• Aucun résultat trouvé

Instanciation, r´ef´erence et expansion d’objets

Eiffel : une approche globale pour programmer et r´eutiliser

2.4 Instanciation, r´ef´erence et expansion d’objets

2.4.1 Retour sur le((halte au tout objet))

Comme annonc´e dans lechapitre 1, les objets peuvent servir, soit `a mod´eliser des comportements dont l’effet est perc¸u par des changements d’´etats, soit des con-naissances plus stables et moins individualis´ees, les valeurs. Pour percevoir le chan-gement d’´etat d’un objet, il faut distinguer son identit´e de sa valeur. Ainsi, on peut dire d’un objet qui repr´esente une horloge qu’il affichait((midi moins cinq))avant d’afficher(( midi)), mais on ne peut parler d’´evolution de la valeur(( midi)). Et

8. Ne pas confondre la surcharge des op´erateurs avec leur red´efinition. En EIFFEL, toute classe peut d´efinir ou red´efinir des op´erateurs comme+, mais une seule fois. Ainsi, le type d’un objet et le nom d’une m´ethode ou d’un op´erateur suffisent `a d´eterminer le code `a utiliser. S’il y avait surcharge comme en C++ ou ADA95, ou multis´election comme en CLOS, il faudrait en plus consid´erer la liste des param`etres pour effectuer cette d´etermination.

d`es qu’on dispose d’un moyen pour distinguer((c’est le mˆeme objet))de((c’est la mˆeme valeur)), on d´ebouche aussitˆot sur la possibilit´e de partage et de copie des ob-jets :((deux employ´es ont le mˆeme chef)). Ainsi, si l’on examine les attributs d’un objet, certains seront propres `a l’objet (l’ˆage, le nom d’une personne), sans v´eritable identit´e, proches des valeurs ; d’autres attributs au contraire seront des r´ef´erences `a des objets externes (des enfants, un chef de service), rep´erables et partageables par d’autres objets. Enfin pour compliquer le tout, il se peut tr`es bien qu’un attribut priv´e ´evolue (par exemple pour corriger un nom), ce qui permet de le consid´erer, `a la fois comme une valeur et comme un objet ´evolutif, mais avec des points de vue diff´erents.

Cette probl´ematique est bien connue du monde des bases de donn´ees ( chapi-tre 5), mais elle a ´et´e singuli`erement n´eglig´ee par tous les concepteurs de langages g´en´eralistes qui se sont d’abord focalis´es sur des probl`emes de repr´esentation en m´emoire, avant de s’int´eresser `a la s´emantique des liens entre objets. Cela ex-plique l’absence de constructions et de m´ecanismes pour exprimer et contrˆoler les diverses s´emantiques des liens de composition [Oussalah, 1997] ou d’association [Cattell et al., 1997] et l’absence de tuples de valeurs... comme le proposent en par-tie les langages de description des bases de donn´ees (chapitre 5) ou d’analyse et de conception (chapitre 4). EIFFELn’´echappe pas `a cette r`egle : il ne fournit que deux m´ecanismes de repr´esentation des attributs, les r´ef´erences et les objets expans´ees, dont la s´emantique colle `a la repr´esentation en machine.

2.4.2 R´ef´erences et objets expans´es

Par d´efaut, une variable contient une r´ef´erence `a une instance de classe. Une r´ef´erence diff`ere d’un pointeur, car elle peut ˆetre impl´ement´ee de diverses fac¸ons sans que cela int´eresse le plus souvent le programmeur : par une adresse d’instance en m´emoire volatile (comme sugg´er´e dans lechapitre 1), une entr´ee dans une table d’indexation de base de donn´ees, uneURLsur le r´eseau... Il n’y a pas de pointeurs en EIFFEL9, sauf pour les interfac¸ages avec C ANSI. D’un point de vue s´emantique, les r´ef´erences permettent d’impl´ementer des partages d’instances.

Une variable peut contenir aussi directement la valeur d’une instance, si la va-riable est d´eclar´ee avec le mot expanded. Sur l’exemple de la figure 2.3, la va-riable expans´eedate naissanceest stock´ee directement dans la repr´esentation des instances dePERSONNE pour la rendre sp´ecifique et solidaire des d´eplacements de ces instances. EIFFELpermet aussi de rendre automatiquement expans´ee toutes les instances d’une((classe expans´ee))dont la signature indiqueexpanded. Ainsi, les types de base commeINTEGER,BOOLEAN,DOUBLE... sont d´ecrits dans des classes ex-pans´ees, car leurs valeurs n’ont presque jamais de signification propre. Les objets expans´es sont de plus anonymes, c’est-`a-dire sans r´ef´erence pour les partager entre plusieurs instances. Mais ce sont de vrais objets, mutables (chapitre 1), instances de leur classe. Ils ont donc n´ecessairement une identit´e, qui peut ˆetre obtenue en associant celle de l’objet qui les contient au nom de la variable expans´ee, mais sans utiliser de r´ef´erence.

class PERSONNE inherit

ETAT CIVIL -- acc`es `a des primitives globales commemasculin, feminin, today... creation creer

feature -- attributs

nom : expanded NAME

prenom : expanded NAME

sexe : INTEGER --masculinoufeminin

date naissance : expanded DATE

feature -- cr´eations

creer (n, p : STRING ; s: INTEGER ; d : STRING) is

-- Cr´eer une personne de nomn, pr´enomp, sexeset date de naissanced. require

nom valide : n /= void and then n.count >=2 and n.count <= 25 prenom valide : p /= void and then p.count >=2 and p.count <= 20

sexe valide : s = masculin or s = feminin

date naissance valide : d /= void and then today.is date valid(d) pas trop jeune : (today -y date(d)) >=0 -- nouveau n´e pas trop vieux : (today -y date(d)) <= 122 -- Jeanne Calment do

nom := n ; prenom := p ; sexe := s date naissance.update from string(d)

ensure

nom = n ; prenom = p ; sexe = s date naissance.is equal(date(d)) celibataire : mariages = Void

end --creer

feature -- accesseurs secondaires etat matrimonial : INTEGER is

do

if mariages = void then Result := celibataire

elseif mariages.max.date fin = void then Result := marie

else Result := divorce

end ensure

Result = celibataire or Result = marie or Result = divorce definition: (Result = celibataire) = (mariages = void)

end -- etat matrimonial feature {NONE}

mariages : ORDERED SET [ MARIAGE ]

-- Ensemble des mariages, par ordre chronologique,Voidsi c´elibataire

feature {MARIAGE} -- Seule la classeMARIAGE a acc`es aux primitives de cette section noter nouveau mariage (m: MARIAGE) is ...

...

FIG. 2.3: Extrait de la classePERSONNE(vue concr`ete).

2.4.3 Instanciation

L’utilisation d’une variable exige la pr´esence d’un objet obtenu par une instan-ciation ou une affectation pr´ealable, sinon cela d´eclenche une exception. En EIF

-FEL, l’instanciation est uniquement dynamique, soit explicite pour les variables de r´ef´erence, soit implicite pour les variables expans´ees, en mˆeme temps que l’instance qui les contient. La notation!T!vcr´ee une instance du typeTet l’affecte `a la variable de r´ef´erencev; par d´efaut!!vcr´ee une instance du type indiqu´e dans la d´eclaration dev.

L’instanciation initialise les champs de l’objet `a la valeur neutre de leur type, mais peut ˆetre combin´ee `a une initialisation explicite, en choisissant l’une des rou-tines de la sectioncreation. Ainsi, pour cr´eer une date (cf. Fig. 2.1, p. 40), on peut ´ecrire!!d.make0 ou!!d.make(14, 7, 1996). La notation!!dest syntaxiquement correcte, mais violerait ici l’invariant de l’instance cr´e´ee, en donnant par d´efaut la valeur0(neutre pour le typeINTEGER) aux champsday,month, year, soit la date

"0/0/0000"qui est invalide.

L’instanciation automatique des variables expans´ees n´ecessite que le compila-teur puisse choisir seul, et sans ambigu¨ıt´e, le m´ecanisme d’initialisation `a effectuer. C’est le cas si la classe est initialis´ee par d´efaut ou s’il n’y a qu’une routine d’initia-lisation sans argument, comme dans l’exemple de la classeDATE(cf. Fig. 2.1, p. 40), grˆace `a son unique initialiseurdate0.

2.4.4 Propri´et´es essentielles et contigentes d’un objet

Tout objet EIFFEL a deux sortes de propri´et´es, un type, et un statut qui sont rep´er´es par des champs distincts dans son en-tˆete. Le type concerne des propri´et´es

essentielles, d’ordre s´emantique10. Le statut caract´erise des propri´et´es contingentes, instables, comme le fait d’ˆetre expans´e, persistant, mobile sur le r´eseau, marqu´e par un ramasse miettes, verrouill´e par une transaction...

Ainsi, l’instruction d’affectation (:=) est contrˆol´ee statiquement par des crit`eres de compatibilit´e s´emantiques et contingente, en consid´erant la faisabilit´e technique comme la taille des objets, la disponibilit´e... Dans le cas de variables r´ef´erenc´ees, il s’agit de l’attachement d’un objet `a la variable ; le polymorphisme ne pose ici aucune difficult´e de taille des variables r´eceptrices, puisque toutes les r´ef´erences ont la mˆeme taille. Pour les variables expans´ees, il s’agit d’une recopie de valeur, champ par champ, qui n’est techniquement possible que si la taille des variables est compatible : le polymorphisme est interdit dans ce cas11. Dans le cas de l’affectation d’un objet expans´e `a une variable r´ef´erenc´ee, il y a clonage (cr´eation d’une instance avec recopie de la valeur) et attachement de l’instance cr´e´e. Dans le cas inverse, il y a recopie de la valeur de l’objet r´ef´erenc´e dans la variable expans´ee.

2.4.5 Discussion sur le m´ecanisme d’expansion

Le m´ecanisme d’expansion est donc de bas niveau et a ´et´e conc¸u au d´epart pour introduire des champs de taille quelconque dans les objets, par exemple pour les nombres r´eels en double pr´ecision. Il ne faut pas l’utiliser sur des crit`eres d’effica-cit´e qui sont tr`es hypoth´etiques. En effet, sauf pour les types de base, l’usage des variables expans´ees ne fait gagner souvent, ni temps d’acc`es, ni place en m´emoire. `A notre avis, la vraie justification de l’expansion devrait ˆetre beaucoup plus s´emantique, sur des crit`eres de partage ou non de valeurs. Cela laisserait l’impl´ementation libre

10. Dans les impl´ementations actuelles, la r´ef´erence au type d’une instance est un simple pointeur `a la r´eification de sa classe, comme indiqu´e dans le mod`ele simplifi´e pr´esent´e auchapitre 1. Dans le cas d’EIFFEL, c’est une erreur, car cela ne permet pas de manipuler correctement les types g´en´eriques.

11. C’est une r`egle trop pessimiste. On pourrait d´eterminer statiquement si la taille des instances des sous-types d’une variable expans´ee permet l’affectation.

de choisir, entre expanser ou r´ef´erencer, pour impl´ementer de mani`ere efficace le partage ou la solidarit´e et supprimerait l’actuelle restriction sur l’affectation poly-morphe entre variables expans´ees.