2.1 La définition de nouvelles classes
Comment faire tout cela en SMALLTALK? Comme nous l’avons dit plus haut,
l’acte principal de la programmation SMALLTALK est la définition de nouvelles
classes avec leurs méthodes et la création d’instances particulières qui sauront
activer ces méthodes.
Puisque nous voulons créer un monde rempli d’animaux, il semble tout
naturel de recréer, au moins en partie, la hiérarchie de la classification des
animaux telle qu’elle est donnée dans un arbre philogénétique. La figure 2.1 donne
un extrait d’un tel arbre.
Recréer cette hiérarchie en SMALLTALK ne nécessite rien d’autre que de créer
une classe Animal, qui pourrait - faute de mieux - être une sous-classe de la classe
Object, et ensuite de rajouter des sous-classes, des sous-sous-classes,
vcorrespondant à chacun des nœuds de la hiérarchie présentée.
Allons-y. Pour créer une sous-classe d’une classe existante – par exemple de la
classe Object – il suffit d’ouvrir un explorateur de classe, de cliquer sur une
catégorie quelconque et de remplir le canevas dans la fenêtre de code pour décrire
la sous-classe qu’on veut créer. La figure 2.2, montre un tel explorateur avec le
canevas que voici:
Object subclass: #NameOfSubclass
instanceVariableNames: ’’
classVariableNames: ’’
poolDictionaries: ’’
category: ’Kernel-Objects’
|
|
Donc, pour créer une classe Animal, il suffit de remplacer le nom de la
sous-classe par défaut, le canevas NameOfSubclass, par le nom de notre nouvelle
classe, Animal dans notre cas, d’insérer les noms des variables d’instances qui
distingueront une instance de la classe d’une autre (un animal d’un autre), et de
remplacer la catégorie Kernel-Objects par le nom de catégorie sous
laquelle nous désirons trouver les différentes classes d’animaux. Pour
l’instant, supposons que nous voulons créer une nouvelle catégorie nommée
Cours-Smalltalk-Animaux et qu’au minimum toute instance d’animal devrait avoir
un nom.1.
Ce qui nous donne:
Object subclass: #Animal
instanceVariableNames: ’nom’
classVariableNames: ’’
poolDictionaries: ’’
category: ’Cours-Smalltalk-Animaux’
|
|
Il suffit alors d’ouvrir le menu contextuel de cette fenêtre, de cliquer sur
accept (ou plus simplement, comme dit dans l’annexe B, de juste taper les
caractères «Alt+s»), et SQUEAK aura compris qu’à partir de maintenant il existe
la nouvelle classe Animal, qui se rajoutera tout naturellement à l’ensemble des
classes déjà existantes. SQUEAK aura également compris que cette classe sera
accessible à travers la catégorie Cours-Smalltalk-Animaux. L’explorateur se
montre alors sous la forme de la figure 2.3.
Notons que la classe Animal a été définie de manière telle que chaque instance
aura une variable d’instance, nom: tout animal possède un nom et ce sera son nom
qui distinguera une instance d’Animal d’une autre.
Notons aussi que nous avons écrit la première lettre du nom de la classe en
majuscule: Animal. En SMALLTALK, le bon style est de capitaliser les noms des
classes, des variables de classes et des pool-dictionaries et, par contre, de débuter
les noms des variables d’instance par un caractère minuscule. Ceci permet au
lecteur de reconnaître immédiatement s’il s’agit de quelque chose qui appartient
aux instances (c’est écrit en minuscule) ou à une classe (c’est capitalisé).
Rappelons que nous écrivons aussi les programmes pour qu’ils soient lus par
d’autres programmeurs!
C’est naturellement de la même manière que nous allons définir les diverses
sous-classes dont nous aurons besoin. Ainsi
Animal subclass: #Mammifere
instanceVariableNames: ’’
classVariableNames: ’’
poolDictionaries: ’’
category: ’Cours-Smalltalk-Animaux’
|
|
crée la classe des Mammiferes qui hérite de la classe Animal la variable
d’instance nom et les méthodes que nous y ajouterons par la suite.
Si nous définissons de la même manière les classes Baleine, Oiseau, Perroquet,
Chien et Pingouin:
Mammifere subclass: #Baleine
instanceVariableNames: ’’
classVariableNames: ’’
poolDictionaries: ’’
category: ’Cours-Smalltalk-Animaux’
|
|
Mammifere subclass: #Chien
instanceVariableNames: ’aboieBeaucoup’
classVariableNames: ’’
poolDictionaries: ’’
category: ’Cours-Smalltalk-Animaux’
|
|
Animal subclass: #Oiseau
instanceVariableNames: ’volant’
classVariableNames: ’’
poolDictionaries: ’’
category: ’Cours-Smalltalk-Animaux’
|
|
Oiseaux subclass: #Perroquet
instanceVariableNames: ’vocabulaire’
classVariableNames: ’’
poolDictionaries: ’’
category: ’Cours-Smalltalk-Animaux’
|
|
Oiseau subclass: #Pingouin
instanceVariableNames: ’’
classVariableNames: ’’
poolDictionaries: ’’
category: ’Cours-Smalltalk-Animaux’
|
|
nous arrivons à un arbre philogénetique (réduit) comme celui qui est
donné dans la Figure 2.4 ci-dessus. Cet arbre montre la hiérarchie de
nos classes SMALLTALK (à partir de la classe Animal) et les lieux où des
variables d’instances sont définies. Celles-ci apparaissent en deuxième ligne
des rectangles représentant les classes. La figure 2.5 montre cette même
hierarchie que nous avons obtenue en ayant selectionné dans un explorateur la
classe Animal et en ayant choisi dans le menu contextuel l’entrée show
hierarchy.
Au risque de nous répéter: puisque la classe Animal définit la variable
d’instance nom, toute instance de cette classe et toute instance de chacune de ses
sous-classes possèdera, par héritage, une variable d’instance nommée nom. Seules
les instances de la classe Chien (et de ses sous-classes éventuelles) possèdent la
variable d’instance aboieBeaucoup, et seules les instances de la classe Oiseau et
de ses deux sous-classes Pingouin et Perroquet possèdent une variable d’instance
nommée volant. Ainsi tout perroquet est défini par ses trois variables d’instance:
nom, volant et vocabulaire; cette dernière étant définie dans la classe
Perroquet.