JavaToScala : syntaxe et concepts

Se mettre à Scala

Actuellement développeur Java / Web, j’apprécie particulièrement Play framework et je commence à vraiment voir de plus en plus de choses sur Scala. C’est pourquoi j’ai décidé de regarder d’un peu plus près ce nouveau langage. Scala est un langage fonctionnel qui s’exécute sur la JVM. Quand on vient du monde Java (comme moi), on remarque tout de suite la concision du langage mais aussi qu’il est à peu près incompréhensible (ça me rappelle ma tentative avortée d’apprendre Haskell…). Maintenant que j’ai un peu plus de recul sur ce langage, que je viens de terminer Functional Programming Principles in Scala et que je débute Principles of Reactive Programming, je vais aborder une série d’articles sur Scala et ses avantages. Car, il est vrai, une fois habitué aux nouveaux concepts, c’est un langage étonnamment puissant.

scala-reactive

Ce qui change de Java

Avant de partir sur les aspects fondamentaux qui font la puissance de ce langage, je vous propose une petite introduction à la syntaxe et aux concepts de base Scala.

Classes et interfaces

Java comme Scala sont des langages objet. Les deux langages reposent donc sur des classes. Même si leur syntaxe varie un peu, les concepts sont assez similaires :

Comme vous pouvez le noter, le code Scala est bien plus concis mais tout aussi clair ! La déclaration de la classe, des attributs et du constructeur se fait en une ligne. Pour la méthode  say , le type de retour est inféré. On remarque aussi que les ; et les {} sont optionnels. Autre différence aussi, les classes Scala peuvent être définies partout dans le code, contrairement à Java où chaque classe doit être dans un fichier qui porte le même nom.

Trait

Pour les interfaces (Java), l’équivalent Scala est un trait. Mais nous allons voir qu’il est finalement bien plus qu’une interface. Tout d’abord, comme une interface, il définit des méthodes qui devront être implémentées dans les classes qui en héritent et, comme en Java, une classe peut hériter de plusieurs trait. Voici les implémentations Java et Scala qui se ressemblent.

Tout d’abord, il faut noter que les deux codes ne sont pas équivalents. Le trait Scala  hasName  implémente la méthode  hello , ce qui est impossible à faire avec les interfaces Java. Un trait est donc à mi-chemin entre l’interface et la classe abstraite Java et profite des avantages des deux (implémentation de méthodes et multi-héritage). Une autre chose, assez étrange, est que lorsqu’une classe étend plusieurs trait, on utilise le mot clé  extends pour le premier et le mot clé with pour les autres. C’est une étrangeté de Scala que je n’explique pas encore (si quelqu’un à une réponse…).

Object

Par ailleurs, Scala offre d’autres structures objet qui peuvent être très utiles. Je parle notamment des  object  et des case class . Les objets sont des classes scala directement instanciées comme des singletons :

Ils font alors référence à une seule instance et peuvent être définis comme des constantes qui offrent toutes les possibilités d’une vraie classe (héritage, composition…). Si une classe et un objet existent avec le même nom, l’objet est alors appelé « companion object ». Ils doivent être définis dans le même fichier source scala. Cet objet permet de définir des attributs ou méthodes globales à cette classe. C’est approximativement la partie static des objets Java. Par exemple :

Case class

Parlons maintenant des case classes. Ce sont des classes qui permettent de faire correspondre une classe avec son contenu. Typiquement, elles permettent de définir de manière pratique de nouveaux types. Comme c’est pas très clair, voici un exemple :

Ce sont des classes normales précédées du mot clé  case . Grâce à ce mot clé, le compilateur va créer un objet compagnon qui nous permet de créer ces classes sans le mot clé new . Il est donc possible d’écrire :

Ce type particulier de classes est aussi très intéressant lorsqu’il est combiné avec le pattern matching, qui est pour moi une des forces de Scala. J’en parlerai un peu plus précisément dans un autre article mais en quelques mots, c’est une sorte de switch case étendu. En Java, un switch case n’est possible que sur des éléments simples et avec des valeurs discrètes (Integer ou Enum) alors que le pattern matching Scala fonctionne sur tout type d’expression. Et en particulier les case classes. Ainsi, si nous voulons afficher une expression, il suffit d’écrire :

Ou de remplacer le toString du trait Expr  :

La déclaration de variables

A la différence de Java, pour créer une variable en Scala, on précise simplement le mot clé  var  sans préciser son type. Celui-là sera automatiquement déduit de l’expression à droite du =. Il existe aussi le mot clé val  pour définir des constantes. Ce mot clé est, contrairement à Java (avec l’utilisation du final), beaucoup plus utilisé que le précédent. En effet, Scala étant un langage fonctionnel, il est préférable de créer de nouveaux objets que de les modifier. Et enfin, il existe le mot clé  def  pour définir des expressions.

Pour voir les subtilités entre ces différents mots clés, je vous propose d’utiliser cette classe qui nous permettra d’afficher « Create MyClass[name] » à chaque fois qu’une instance est créé :

Commençons par le mot clé  var  :

Comme nous pouvons le voir, un objet est créé aux lignes 1 et 3 grâce à l’opérateur  new . Et les lignes 2 et 4 affichent bien les contenu attendu.

Avec le mot clé  val (ou final en Java), impossible de réaffecter un nouvel objet à la constante c , le compilateur le refuse !

Nous pouvons donc créer l’objet une première fois mais pas le réaffecter comme c’est fait en ligne 3 avec le  var .

Pour le mot clé  def , les choses sont encore différentes. On définit une expression :

Comme pour le mot clé  val , impossible de redéfinir l’expression. En revanche, on remarque qu’à la ligne 1 aucun objet est créé. C’est simplement l’expression qui est définie, une sorte d’alias. Et dès que l’on souhaite l’utiliser (l’afficher par exemple), l’expression est évaluée, ce qui entraîne la création d’un objet de type MyClass . Et cela, à chaque fois !!! d  n’est pas un objet de type  MyClass  mais une expression qui exécute  new MyClass("def") lorsqu’elle est évaluée.

Conclusion

J’espère que cet article vous permettra de lire un peu plus facilement le code Scala. Comme c’est une première pour moi d’écrire de tels articles, n’hésitez pas à faire des remarques constructives dessus 😉

2 réponses à “JavaToScala : syntaxe et concepts

  1. Trés bonne introduction au langage.

    – Pour moi, la première différence avec Java est les fonctions qui sont des first-class value.
    val f = { x: Int => x * x}

    – A extends B with C doit être lu comme A extends (B with C). Autrement dit, A étend un B mixé avec un C.

    – case class est un équivalent des ValueObject, et le compilateur Scala génère pour nous les méthodes toString, equals, hashCode. Ton exemple de trait Expr va plus loin, c’est un ADT (Algebraic Data Type).

    – Et l’immutabilité est souhaitable aussi en Java 🙂

    Quelques typos :
    s/étends/étend
    s/parlerais/parlerai

    • Loïc Knuchel

      Merci pour ton retour et tes précisions.
      Je comprends mieux le extends/with !

      Effectivement la grosse différence est sur les fonctions, j’ai d’ailleurs prévu d’y consacrer un article. 🙂
      Le but de ce premier article était d’expliquer un peu les différence de syntaxe et de concepts qu’il pouvait y avoir pour que des développeurs Java puissent lire du code Scala un peu plus facilement.

      L’immutabilité est possible et souhaitable en Java mais le langage fait que ce n’est pas naturel (mettre final devant toute ses variables…).

Répondre à yann Annuler la réponse

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">