Introduction à Scala: Classes et Objets

ScalaDans ce second volet de l’introduction à Scala, je vais présenter comment définir et utiliser les classes et les objets avec Scala.

1. Classes

1.1. Définition d’une Classe

Je vais commencer par les classes. Scala ne joue pas aux fantaisies ici, et une classe est toujours une structure regroupant champs et traitements.

Voici la déclaration minimale d’une classe en Scala

class Person

A l’inverse de Java, une classe est par défaut publique, donc plus besoin d’ajouter public à la déclaration.
D’ailleurs, le mot public n’existe même pas pour Scala.
Là, on peut se poser la question de ou est passé le modificateur de visibilité par défaut de Java, qui limite l’accès à un champ/classe au package dans lequel il/elle est défini ?
Scala va beaucoup plus loin (encore une fois) que Java en offrant un contrôle très précis de qui a le droit d’accéder à tel ou tel champ/classe, mais ce n’est pas dans le cadre de ce billet.

1.2. Définition des champs

Ajoutons maintenant quelques champs à cette classe, ce qui donne:

class Person

La déclaration d’un champ se présente comme suit:

[modificateur de visibilité] (var|val) nom [:Type] [= Valeur]

les parties entre [ et ] sont optionnelles, et (x|y) indique un choix exclusif entre deux options x et y.
var indique qu’un champ est muable tandis que val indique qu’un champ est immuable.

Une note importante s’impose: si un champ n’est pas initialisé avec une valeur lors de sa déclaration, il est considéré par Scala comme champ abstrait.

Vous êtes déjà habitués aux méthodes et classes abstraites dans Java. Scala va encore plus loin en étendant cette notion au champs aussi.

Ainsi, il est nécessaire d’assigner une valeur à un champ lors de sa déclaration si on ne veut pas qu’il soit considéré comme abstrait.

Dans le cas où on n’a pas de valeur précise à assigner comme valeur par défaut à un champ, on peut utiliser le ‘wild card‘ _ de Scala comme valeur, comme ici:

class Person

Le ‘_’ serait traduit par le compilateur en la valeur adapté au type du champ, 0 pour les Int, “” pour les chaînes, etc.

Optimisons encore la chose en tirant profit du puissant système d’inférence de types de Scala, qui nous permet de ne pas avoir à declarer le type d’un champ du moment que ce même type peut être déterminé depuis la valeur d’initialisation:

Inférence de types

Tout comme pour les classes, les champs dans Scala sont publics par défaut.

Voici maintenant comment on peut instancier une telle classe et l’utiliser:

Classe de Test

Là, je vois déjà les puristes OO en désarroi face à cette absence d’encapsulation: accès direct aux champs ?? !!

Rassurez vous, même si ça en a tout l’air, ‘under the hoods‘, Scala alloue un espace mémoire pour un champ inaccessible au programmeur, et génère automatiquement l’équivalent d’un getter et d’un setter Java et ce sont eux qui sont invoqués lors de la lecture et écriture (plus de détails dans la suite).

1.3. Constructeurs

a. Constructeur principal

Je vais maintenant montrer une autre fonctionnalité puissante de Scala qui s’adapte bien à ce genre d’objets (conteneurs de données): les constructeurs.

Les constructeurs d’une classe dans Scala sont un peu différents de ceux en Java, et sont considérés des ‘first class citizens‘.

Voici comment on définit le constructeur principal d’une classe Scala:

class Person(var name: String, var age: Int)

Yep, la classe tient désormais sur une seule ligne ;)
Ce bout de code définit à la fois les deux champs name et age ainsi qu’un constructeur qui prend les valeurs de ces deux champs comme paramètres.

Voici comment instancier une telle classe:

instantiation d'une classe

Qui comme vous le remarquez est similaire à ce qu’on fait en Java.

b. Constructeurs auxiliaires

Maintenant, la question qui se pose, est comment déclarer, tout comme dans Java, d’autre constructeurs de signatures différentes ?
C’est tout à fait logique vu comment est défini le constructeur principal.

Scala impose la limite suivante: on peut définir d’autres constructeurs, mais ils doivent obligatoirement invoquer directement ou indirectement le constructeur principal.

Voici comment déclarer d’autres constructeurs (secondaires ou auxiliaires):

Constructeurs secondaires

Et voici comment invoquer ces nouveaux constructeurs

Instantiations

Les constructeurs secondaires peuvent très bien effectuer d’autres traitements, comme dans ce cas par exemple:

Constructeur auxiliaire

Mais la règle d’invocation du constructeur principal tient toujours. Ici, ça se fait indirectement.

1.4. Getters et Setters

La question suivante est comment spécifier par exemple son propre getter et setter pour un champ ainsi défini ?

Voici comment ça se fait:

getter et setter
J’ai d’abord ajouté private à la déclaration de age dans le constructeur (en le renommant en a du même coup) et défini deux méthodes (via le mot clé def):

  • age: qui ne fait que retourner le champ privé a en lui ajoutant la chaine ” ans”, d’où le type de retour en String. Remarque que j’aurais pu retourner a directement et mettre le type en Int, c’est juste pour montrer les possibilités …
  • age_= : oui, ‘age_=’ est un identificateur valide en Scala. Cette méthode prend un paramètre de type Int, et teste s’il est positif, auquel cas elle affecte sa valeur au champ a, autrement elle lance une exception.

Voici maintenant un bout de code qui teste ce qu’on a fait:

Test getter et setter

p.age qui est passé à println invoque bel et bien le getter qu’on a défini, et retourne “25 ans”.
p.age = 15 invoque le setter et ça passe, vu que 15 > 0
p.age = -5 lance une exception, comme prévu ;)

2. Objets

2.1. Définition

Passons maintenant aux objets.
Les objets sont une notion spécifique à Scala (par rapport à Java) et se présentent entre autres comme remplaçant du contexte static de Java (inexistant dans Scala).
Dans la section précédente, j’ai montré comment définir une classe (une partie du moins).
Une classe ne définit que la structure de l’entité, mais pour l’utiliser, il faut l’instancier dans un conteneur pour pouvoir la manipuler.

Un objet est tout comme une classe dans la mesure où il définit la structure, mais il définit aussi l’instance, ce qui permet de le manipuler directement, sans avoir à l’instancier dans un conteneur.

Seulement, dans Scala, il s’agit plutôt d’un Singleton, crée, et maintenu par le compilateur.
Un objet est crée la première fois qu’on y accède, et c’est cette même et unique instance qui sera partagée entre tous ses clients.

2.2. Exemples

a. La méthode main

L’exemple le plus courant de l’utilisation des objets dans Scala est tout comme Java, pour définir la fonction main, le point d’entrée d’un programme.
Une telle méthode doit obligatoirement être définie dans un Objet, comme dans le montre cet exemple:

main
La déclaration d’un objet utilise object au lieu de class.

b. Le cas général

Voici un autre exemple où l’on définit une méthode utilitaire (square) pour pouvoir l’invoquer sans avoir à instantier une classe (comme Math de Java):

object Calc

On peut dès lors accéder directement à la méthode square:

Appel de méthode d'un objet

Pour tout le reste, les objets et les classes dans Scala se présentent de la même façon, excepté l’absence de constructeurs, qui n’ont plus aucun sens dans un objet.

3. Conclusion

Voilou, c’est la fin de ce (long) billet, qui a présenté quelques notions de base sur la définition et l’utilisation des classes et des objets dans Scala.
Le billet suivant de la série “Introduction à Scala” couvrirait les méthodes et les fonctions, qui sont des entités à part entière dans Scala et permettent de faire des choses très intéressantes …

Changelog

=> 11/07/08: J’ai corrigé la partie sur les constructeurs suite à un retour de gorgonite (à propos du currying). Merci à lui.

—-

Advertisements

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: