Formation Smalltalk, tutoriel & guide de travaux pratiques en pdf.
Les collections
Présentation
Les collections sont une famille de classes fournissant un support pour la gestion des données et l’algorithmique de base.
La classe Collection est la racine de l’arborescence conduisant aux différentes classes. Elle n’a pas directement d’instances, c’est une classe “abstraite”, mais elle occupe une position logique et propose un jeu de messages que l’on retrouvera dans les sous-classes.
Ce document présente d’abord les niveaux et les classes de la hiérarchie, et les messages les plus significatifs acceptés ou refusés par les classes. Dans un second temps on trouve une description des messages les plus courants accompagnés d’exemples illustrant les principaux usages que l’on peut en faire.
Classification des collections
Chaque noeud dans l’arbre correspond à une, ou un petit nombre de propriétés et opère une disjonction en sous-arbres en fonction de cette propriété. Par exemple (section 2.2.1), la classe Collection amène à disjoindre les classes ne disposant pas d’ordre (Bag, Set) des classes qui en disposent (SequenceableCollection).
Hiérarchie simplifiée
La hiérarchie des collections est accessible dans le brosseur Smalltalk en sélectionnant la classe Collection, et dans le menu de la deuxième sous-fenêtre l’option hierarchy. Il faut noter que certaines classes d’applications
Méthode de programmation
Le code Smalltalk-80 est le plus dense parmi ceux des langages de programmation courants. Cette densité est liée à la réutilisation de mécanismes ouverts, fiables et bien organisés. C’est le cas des collections.
Ecrire moins de code c’est gagner sur deux plans : la productivité, et la fiabilité.
Dans le cas des collections, on peut effectuer les recommandations suivantes :
1. Prise en main du cadre de programmation :
(a) Apprendre les caractéristiques des classes majeures dans la hiérarchie (propriétés caractéristiques au sens de la classification, et principaux messages).
(b) Apprendre les messages principaux.
2. Développer des réflexes de programmation par rapport à ce cadre :
(a) Identification du besoin, ou de la succession de besoins à un stade du problème en cours d’analyse.
(b) Identification des classes et méthodes permettant de recouper ce besoin, et implémentation via les messages et les conversions de classes.
Illustration
Dans les exemples qui suivent on montre deux enchainements conduisant à la solution du problème posé. Ces enchainements sont basés sur des successions de propriétés trouvées pour aboutir à la propriété réalisant la question posée.
Exemple 1 Soit la chaine s :=’une chaine de caractère’.
Compter le nombre de voyelles.
Compter les mots (séparés par des blancs).
| s |
s:=’une chaine de caractère’.
(s select: [ :char | char isVowel] ) asSet size » 5″
« Algo: Extraire les voyelles, enlever les doublons, compter »
| s mots |
s:=’une chaine de caractère’.
mots := ( s tokensBasedOn: $ ) reject: [:mot | mot isEmpty].
mots size « 4 »
« Algo: Casser en mots, enlever les mots vides, compter »
Classification par propriétés
Collections avec ou sans ordre
Le premier exemple de disjonction se trouve au niveau 2 de la hiérarchie où l’on disjoint les sous-classes de Collection disposant d’un ordre (Sequen-ceableCollection), des classes sans ordre (Bag et Set)
Notion d’ordre dans les éléments des collections
– Bag and Set n’ont pas d’ordre, et leurs éléments ne peuvent pas être désignés par une clé externe.
– Les doublons ne sont pas possibles dans les ensembles (Set).
– Les éléments des SequenceableCollection sont ordonnés, soit par un ordre externe comme dans le cas des ArrayedCollection, soit par un mécanisme interne comme dans le cas des Interval.
– Les messages requis au niveau de la classe Collection sont listés si-dessous. Attention, certains de ces messages sont parfois interdits dans quelques sous-classes (add: dans Array), ou redéfinis plus efficacement (add: dans les Set).
– D’autres messages sont reconstitués en utilisant les messages requis, comme c’est le cas pour collect: en utilisant do
Collections sans ordre : les ensembles et les sacs
Set est une collection dynamique dont l’interface est basée sur l’ajout et la suppression. Au moment de l’ajout, on vérifie si l’élément existe ou pas afin de ne pas provoquer de doublons.
– Set permet un certain nombre d’opérations ensemblistes directement (soustraction -), ou via l’interface des collections (addAll : . . .).
Bag a un interface similaire à Set. Au moment de l’ajout, on incrémente un compteur associé à chaque élément du sac. Si on ajoute un très grand nombre d’éléments identiques à un Bag, celui-ci reste petit. D’autre-part le comptage est immédiat.
Les dictionnaires
Dictionary est une classe héritant de Set. Les éléments des dictionnaires sont des associations couplant une clé et une valeur. L’unicité de l’association est as-surée au niveau de la clé : on ne peut pas ranger deux éléments différents
La classe Association
Pour créer une association on utilise en règle générale le message binaire >. Le receveur est une clé qui fixe le “nom” de l’association, et l’argument
est la valeur.
| asso |
asso := #Nono->12.
asso key. « #Nono »
asso value. « 12 »
La clé n’est pas nécessairement un symbole. On peut utiliser n’importe quel objet, par exemple des nombres :
| asso1 asso2 |
asso1 := 4->12.
asso2 := 12->18.
asso1 key = asso2 key. « false »
asso1 value = asso2 value. « false »
Dictionary : création et insertions
Une fois le dictionnaire créé, on peut insérer des éléments avec le message at:put:. Alternativement, on peut aussi ajouter des associations. Pour lire une valeur, on adresse le dictionnaire avec le message at: .
| dictio |
dictio := Dictionary new.
dictio add: 4->12.
dictio. » Dictionary (4->12 ) »
dictio at: 12 put: 18.
dictio. « Dictionary (4->12 12->18 ) »
dictio at: 4. « 12 »
Itérations sur les dictionnaires
Pour itérer sur un dictionnaire, on a plusieurs choix :
– keysAndValuesDo: [ :key :value | ] : permet de disposer à la fois de la clé et la valeur. Voir l’exemple donné en 7.
– associationsDo: [ :asso | ] : meme possibilité si on veut bien ex-traire la clé et la valeur de l’association.
– keysDo: [ :key | ] : permet de balayer l’ensemble des clés.
– collect: [ :valeur | ] : les messages collect : . . .portent sur les valeurs et non les associations ou les clés.
Accès aux dictionnaires
Pour extraire les clés, on adresse le message keys au dictionnaire. Le résultat est un Set. Pour extraire les valeurs, on adresse le message values. Le résultat est un Bag. On peut ajouter des associations, on ne peut pas enlever d’éléments.
Collections séquençables, avec ordre interne ou externe
Le second cas de disjonction se trouve au niveau 3 de la hiérarchie où l’on sépare les sous-classes de SequenceableCollection selon que l’ordre soit une notion interne (Interval) ou externe (ArrayedCollection, OrderedCollection).
Qualité interne ou externe de l’ordre
– Interval dispose d’un ordre interne permettant le séquencement à partir d’une valeur de départ (start), jusqu’à une valeur finale (stop), en utilisant un pas (step)
– ArrayedCollection et OrderedCollection rangent les éléments en fonction des opérations d’accès (at: at:put:) ou d’ajouts (add: remove:).
– Toutes ces classes sont indexables par des entiers à l’aide des messages at: et at:put: (sauf Interval).
– Elles permettent la recherche d’un élément selon leur ordre (findFirst:).
– Elles autorisent des copies de sous-ensembles.
– Elles permettent la création de Stream en lectures ou écritures, et des opérations plus complexes telles que l’éclatement basé sur un élément
La hiérarchie des tableaux
ArrayedCollection est le chapeau de la hiérarchie des tableaux, collections de dimension fixe et indexables par des entiers. Ses deux classes les plus im-portantes sont Array et CharacterArray. La classification sous-jacente repose sur les classes d’objets enregistrés.
– Ces classes servent de support à des fonctionalités pour des classes particulières d’éléments.
– CharacterArray est la racine des classes gérant une variétés de chaines de caractères avec des fonctionalités particulières (String, Symbol, Text).
– D’autres classes (ByteArray) servent de support aux interfaces avec le matériel : réseau, visualisation. . .
Les collections ordonnées
OrderedCollection est une collection disposant de l’indexation et de la dynamicité de l’espace de rangement (add: remove:). SortedCollection est
une OrderedCollection où la position d’insertion est commandée par une clé de tri, et non un index donné par l’utilisateur.
– Ces deux collections changent de taille pour s’adapter aux besoins et cela de manière transparente.
– OrderedCollection peut être utilisée pour décrire des piles, ou des queues.
2.3 Nomenclature des messages
2.3.1 Itération do :
uneCollection do : [ :elt j ]
Ce message itère sur la collection en appliquant le bloc paramètre à cha-cun de ses élément. Le résultat est l’objet uneCollection non modifié.
Exemple 2
| max |
max := SmallInteger minVal.
#( 3 7 -2) do: [ :i | max := i max: max ].
max » 7, le maximum du tableau »
Exemple 3
| max |
max := 1.
(1 to: 200) do: [ :i | i printString reverse = i printString ifTrue: [ max:=i] ]. max » 191, le plus grand palyndrome de l’intervalle 1,200 »
Exemple 4
’verbatim’ do: [ :char | char isVowel ifTrue:
[Transcript show: (String with: char) ; space ] ].
« imprime e a i, les voyelles de la chaine initiale »
Exemple 5
| aSet |
aSet := Set withAll: ’verbatim’.
aSet do: [ :char | Transcript show: (String with: char) ; space
« imprime v i m a b e r t les caractères de la chaine initiale »
].
Itération keysAndValuesDo :
uneCollection keysAndValuesDo : [ :key :elt j ]
Ce message itère sur la collection en appliquant le bloc paramètre à cha-cun de ses élément associé à sa clé. Le résultat est l’objet uneCollection non modifié. Ce message est effectif sur les collections séquenceables et les dictionnaires.
Exemple 6
| somme |
somme := 0.
#( 3 7 -2) keysAndValuesDo: [ :index :nombre |
somme := somme + (index * nombre) ].
somme « 11 = (1*3) + (7*2) +(3*-2) »
Exemple 7
| somme dico |
dico := Dictionary new.
dico at: 2 put: 10; at: 11 put: -2.
somme := 0.
dico keysAndValuesDo: [ :index :nombre
somme « -2 »
| somme :=
somme + (index * nombr
Exemple 8
| dico |
dico := Dictionary new.
dico at: #nono put: 10; at: #nini put: 5.
dico keysAndValuesDo: [ :nom :nombre |
Transcript show: nom asString; tab; show: nombre printString ; c
Itération reverseDo :
uneCollection reverseDo : [ :elt j ]
Ce message est similaire à do: mais opère du dernier élément vers le premier élément. Il est opérationnel sur les collections disposant d’un ordre.
Itération do : separatedBy :
uneCollection do : [ :elt j ] separatedBy : [ ]
Ce message itère sur la collection en appliquant le bloc paramètre à cha-cun de ses élément associé à sa clé. En plus du comportement normal du do:, il permet de provoquer une évaluation entre chaque élément de la collection.
Exemple 9
| chaine |
chaine := String new.
#( 1 2 3) do: [ :nombre | chaine := chaine , nombre printString ]
separatedBy: [ chaine := chaine, ’ et ’ ].
chaine » ’1 et 2 et 3’ »
Itération collect :
uneCollection collect : [ :elt j ]
Ce message itère sur la collection en appliquant le bloc paramètre à cha-cun de ses éléments. Les résultats sont accumulés dans une nouvelle collection d’une classe identique ou proche de la classe initiale (par exemple un Interval rendra un Array). Cette nouvelle collection est rendue en résultat.
Exemple 10
| max maxProgres |
max := SmallInteger minVal.
maxProgres := #( 3 7 -2) collect: [ :i | max := i max: max ].
maxProgres » #(3 7 7) »
Exemple 11
| nombres |
nombres := (17 to: 27 by: 2) collect: [ :i | i printString reverse asNumber nombres » #(71 91 12 32 52 72) Noter que ce n’est plus un intervalle, mais
Exemple 12
| aSet |
aSet := Set withAll: (-7 to: 7 by: 2). » Set (1 3 5 -7 7 -5 -3 -1) »
aSet collect: [ :i | i squared ]. « Set (1 9 49 25) »
« Noter que la classe initiale a été conservée »
Itération select :
uneCollection select : [ :elt j ]
Ce message itère sur la collection en appliquant le bloc paramètre à chacun de ses éléments. Les éléments pour lesquels le bloc est vrai sont accumulés dans une nouvelle collection d’une classe identique ou proche de la classe initiale. Cette nouvelle collection est rendue en résultat.
I Programmation
1 Classes : rappels, et pratique
2 Les collections
3 Stream : les accès séquentiels
4 Set, Dictionary et Bag
II Interfaces standards et spécifiques
5 Construction d’interfaces standard
6 Usage des images dans MVC
III Outils de développement
7 Mise au point des programmes
8 Partager et gérer les développements
9 Conditionnement d’une application
10 Interface vers des librairies externes