Dans cette séquence, nous allons aborder Pharo en le comparant avec un autre langage de programmation objet comme Java.
Alors, en Pharo, on ne manipule que des objets. On effectue des traitements uniquement grâce aux messages et à l'assignation de valeurs dans des variables.
La présetation suivante va vous montrer quelques équivalences entre Java et Pharo pour bien comprendre les différences et les ressemblances.
ArrayList<String> strings = new ArrayList<String>();
Ci-dessus un exemple en Java de création d'une nouvelle collection qui contient des chaînes de caractères et l'affectation de cette nouvelle collection dans une variable appelée strings
.
Ci dessous voici l'équivalent en Pharo. C'est la même chose, la classe qui gère les collections s'appelle OrderedCollection plutôt qu'ArrayList, mais le comportement de cette collection est le même.
strings := OrderedCollection new.
Alors plusieurs choses sont à noter:
new
en Pharo, c'est l'envoi d'un message à une classe. Donc, c'est l'envoi du message new
à la classe OrderedCollection
qui va créer une nouvelle instance de cette collection. En Java, le new est placé devant. Cette construction syntaxique est particulière à l'instanciation d'objets en Java, alors que pour Pharo, c'est juste un envoi de message complètement standard.strings
est une collection.Autre comparaison ou équivalence, cette fois pour la création d'un processus fils. On a un bout de code qu'on voudrait voir exécuter dans un autre processus.
Thread regThread = new Thread( new Runnable() { @Override public void run(){ this.doSomething(); } }); regThred.start();
Ci-dessus en Java, on est obligé de créer une nouvelle instance de la classe Thread
en lui donnant un objet Runnable
en paramètres. Donc, on fait un new Runnable et à l'intérieur comme Runnable est une classe abstraite, il faut définir une méthode qui lui manque. Donc la méthode s'appelle run()
et son contenu, c'est le code qu'on veut pouvoir exécuter dans un processus fils: ici, c'est this. doSomething()
. Ce code-là, la méthode doSomething() appartient à la même classe que celle où ce code se trouve.
En Pharo, on va pouvoir constater que la syntaxe est beaucoup plus simple:
[ self doSomething ] fork
Et à la fin de l'exemple de syntaxe Java, le regThred.start();
va permettre de lancer le processus fils.
En Pharo, c'est ce qu'on va pouvoir faire grâce au message fork. Donc c'est un message qui est envoyé au block.
Depuis Java 8, la syntaxe s'est bien améliorée.
new Thread(()->this.doSomething()).start();
On voit que le code est beaucoup plus clair en Java maintenant.
Pour rappel en Pharo il y a trois types de messages:
" Message Unaires" 5 factorial. Transcript cr. "Messages Binaires" 3 + 4. 5 -> 10. " Messages à mots clés" Transript show: 'Hello world!'. 2 between: 0 and: 5.
factorielle
qu'on a déjà pu voir. C'est aussi le cas de la méthode cr
qui permet d'afficher une ligne vide dans la console.→
, ça permet de créer une paire donc avec une clé et une valeur: donc 5 → 10, ça crée la paire (5, 10);show:
. Il s'envoie sur l'objet Transcript
et il prend un paramètre qui est la chaîne de caractères affichée dans la console. Et dans le deuxième exemple, le message, c'est between: and:
. C'est un message articulé en deux mots clés. Il prend deux arguments et il s'applique sur un receveur. Donc, le message between: and:
s'applique sur l'objet 2 et prend les arguments 0 et 5.De nouveau comparons à Java, surtout par rapport au troisième type de message, les messages à mots clés, c'est ceux-là qui ont une grosse différence par rapport à Java.
receiver.keyword1keyword2(arg1, arg2)
En Java, on a un receveur, un point, le nom du message qu'on envoie à l'objet et les arguments séparés par des virgules entre parenthèses.
En Pharo, on exprime la même chose en séparant les différents mots clés du nom de la méthode et en mettant les arguments au milieu.
anObject keyword1: arg1 keyword2: arg2
Si on prends un exemple concret, on souhaite envoyer le message send
à un objet postman
(facteur) dans le but d'envoyer un courrier à un destinataire. Ci-dessous la syntaxe Java:
postman.send(mail, recipient);
On va la décomposer petit à petit cette syntaxe Java, pour arriver jusqu'à la syntaxe Pharo.
En première étape, on extrait les parties qui sont syntaxiques de Java: le point, les parenthèses, la virgule et le point-virgule. On obtient alors l'expression
postman send mail recipient
Si on transforme ça en phrase pour simplifier la lecture:
postman sent mail to recipient
C'est plus facile à lire, et pour avoir une syntaxe correcte Pharo, on ajoute les deux points. Donc ici, il y a un message:
postman send: mail to: recipient.
Le message send: to: est envoyé à postman et prend deux arguments: le courrier (mail) et le destinataire (recipient).
Les structures conditionnelles comme if, else et les boucles do, for, etc. , tout ça, ce sont des mots clés en Java.
En Pharo, on n'a pas ces mots-clés. Ce ne sont pas des mots particuliers qui sont définis au niveau du langage et du compilateur. Ce sont juste des messages qu'on va envoyer à certains types d'objets.
fullName isEmpty ifTrue: ['FistnameLastname'] ifFalse: [fullname']
En Pharo par exemple pour faire un if
, on envoie le message ifTrue: ifFalse:
, donc c'est un message qu'on envoie à un booléen et qui prend deux blocks en paramètres, un block qui est exécuté si le booléen est vrai et un block est exécuté si le booléen est faux.
De la même façon, les boucles sont juste des messages qu'on envoie à certains types d'objets.
" Equivalents d'une boucle for" 4 timesRepeat: [self doSometing]. 0 to: 100 do: [:i| ...]. " 2 0 à 100 par pas de 2 unités" 0 to: 100 by: 2 do: [i:| ...]. " Execute un block sur les éléments d'une liste" aCollection do: [each| ...].
Pour la première expression de l'exemple, on a l'objet 4, c'est en nombre, on lui envoie le message timesRepeat:
avec un block en paramètres. Et la méthode sous-jacente va exécuter le block, le nombre de fois indiqué par le receveur.
De la même façon, le message to: do:
est envoyé à un nombre et prend un nombre et un block en paramètres et là, entre la valeur i qui est le paramètre du block va prendre toutes les valeurs entre 0 et 100. De la même façon, le message de to: by: do:
, prend en plus, un pas. Et donc i va prendre les valeurs de 0 à 100, mais seulement les multiples de 2, donc 0, 2, 4, 6, etc.
Enfin le message envoyé à une collection est l'équivalent d'une boucle for each en Java et donc va exécuter le block pour chaque élément de la collection. La variable each qui est ici va d'abord prendre la première valeur qui se trouve dans la collection, donc le premier élément de la collection. Le block va être exécuté avec cette valeur each. Puis each va prendre le deuxième élément de la collection. Le block va être exécuté avec cette valeur de each jusqu'à la fin de la collection.
En résumé, il y a trois types de messages:
L'ordre de précédence, c'est:
Les conditions et les boucles sont juste des messages qui sont envoyés à un certain type d'objets contrairement à d'autres langages comme Java, où des mots clés sont définis par le langage avec des instructions particulières au niveau du compilateur.