mars
2008
Suite à la série très intéressante de sondages publiés dans les forums Java de Développez.com à propos de quelques propositions d’ajout de fonctionnalités dans Java 7, j’ai essayé de voir ce que Scala offrait déjà et qui répondaient à ces propositions.
Je vais procéder comme suit: je vais itérer sur chaque proposition (13 en total), présetnatn brièvement chacune (le problème et les propositions dans Java 7). S’en suit la solution Scala à ce problème, si elle existe bien évidemment
=> JDK 7: Proposition 1 : Constructeurs simplifiés pour la généricité
Problème:
Java
Map<String, List<String>>
anagrams = new HashMap<String, List<String>>();
Proposition:
Java
Map<String, List<String>>
anagrams = new HashMap<>();
Scala: Supporte ceci déjà:
Scala
var hm: Map[String, List[Int]] = new HashMap()
=> JDK 7: Proposition 2 : Créer facilement des Collections génériques vides
Problème:
Java
public <E> Set<E> emptySet() { … }
void timeWaitsFor(Set<Man> people) { … }
// * Won't compile!
timeWaitsFor(Collections.emptySet());
// OK
timeWaitsFor(Collections.<Man>emptySet());
Proposition:
Java
public <E> Set<E> emptySet() { … }
void timeWaitsFor(Set<Man> people) { … }
// OK
timeWaitsFor(Collections.emptySet());
Scala supporte ceci déjà:
Scala
def test(d: List[String]) = { ... }
test(Set())
De même pour List et Map.
=> JDK 7: Proposition 3 : Comparer les énumérations
Je suis totalement contre cette proposition, alors je vais passer.
=> JDK 7: Proposition 4 : possibilité d’utiliser les String dans les switch case
Problème:
Java
static boolean booleanFromString(String s) {
if (s.equals("true")) {
return true;
} else if (s.equals("false")) {
return false;
} else {
throw new IllegalArgumentException(s);
}
}
Proposition:
Java
static boolean booleanFromString(String s) {
switch(s) {
case "true":
return true;
case "false":
return false;
default:
throw new IllegalArgumentException(s);
}
}
Scala supporte déjà une forme beaucoup plus puissante et flexible du switch de Java, qui le pattern matching:
Scala
def booleanFromString(s : String):Boolean = {
s match {
case "true" => true
case "false" => false
case _ => error("Illegal argument")
}
}
Le pattern matching de Scala fonctionne non seulement avec les chaînes, mais aussi avec toute autre classe (à condition qu’elle soit déclarée avec le mot clé case) et avec le XML.
=> JDK 7: Proposition 5 : extensions de méthodes
Pas d’équivalent Scala à ce que je connaisse, mais Scala offre un mécanisme ressemblant qui est le « implicit conversion« .
=> JDK 7: Proposition 6 : Invocations chainées
Pas d’équivalent Scala à ce que je connaisse, et j’aime pas trop cette proposition non plus !
=> JDK 7: Proposition 7 : Pouvoir catcher plusieurs exceptions en une fois
Je ne vais pas m’attarder sur ce point, mais en gros, Scala permet de faire du pattern matching sur les exceptions, ce qui ressemble à la proposition.
=> JDK 7: Proposition 8 : rethrow exceptions
Pas d’équivalent Scala à ce que je connaisse, mais de toute façon, la gestion des exception de Scala est un peu différente de celle de Java.
=> JDK 7: Proposition 9 : Notation de tableau pour List et Map
Problème:
Java
//list
list.set(i, list.get(j));
list.set(j, s1);
//map
value = map.get(key);
map.put(key, value);
Proposition:
Java
//list
list[idx] = list[idx];
list[idx] = s1;
//map
value = map[key];
map[key] = value;
Scala supporte déjà ceci grâce à l’interprétation spéciale des méthodes apply et update:
Java
//list
list(idx)=value
//map
value=map(key)
map(key)=value
=> JDK 7: Proposition 10 : Le même type
Problème:
Java
class Buffer {
Buffer flip() { … }
Buffer position(int newPos) { … }
Buffer limit(int newLimit) { … }
}
class ByteBuffer extends Buffer {
ByteBuffer put(byte data) { … }
}
ByteBuffer buf = ...;
buf.flip().position(12); // OK
buf.flip().put(12); // Error
((ByteBuffer)(buf.flip())).put(12); // Obliged to cast
Propositions:
Java
//utiliser this comme type de retour
class Buffer {
this flip() { … }
this position(int newPos) { … }
this limit(int newLimit) { … }
}
class ByteBuffer extends Buffer {
this put(byte data) { … }
}
//Ou encore This
class Buffer {
This flip() { … }
This position(int newPos) { … }
This limit(int newLimit) { … }
}
class ByteBuffer extends Buffer {
This put(byte data) { … }
}
Scala: Supporte déjà ceci en déclarant le type de retour comme « this.type »
=> JDK 7: Proposition 11 : Typedef
But: « créer une espèce d’alias ou de raccourcis » vers un type.
Propositions:
Java
//Proposition 1
import java.util.Map<String,String> as MyProperties;
import java.util.Map<String,T> as Lookup<T>;
//Proposition 2
static class MyProperties = Map<String,String>;
static class Lookup<T> = Map<String,T>;
Scala: Support partiel dans la mesure où l’on peut renommer un type lors de son import:
Scala
import scala.collection.mutable.{Map, HashMap => HM}
=> JDK 7: Proposition 12 : déclaration des propriétés
Problème: getters et setters superflues.
Proposition:
Java
public class Person {
public property String forename;
public property int age;
}
Scala:
Scala
class Person(var name: String, var age: Int)
(Je suis sérieux, une seule ligne)
=> JDK 7: Proposition 13 : Accès aisé aux propriétés
Propositions:
Java
public class Person {
public property String forename;
public property int age;
}
Person p = new Person();
//Version 1
p.forename = "Stephen"; // calls setter
String str = p.forename; // calls getter
//Version 2
p=>forename = "Stephen"; // calls setter
String str = p=>forename; // calls getter
//Version 3
p#forename = "Stephen"; // calls setter
String str = p#forename; // calls getter
Scala:
Java
class Person {
private var n: String=""
def name = n
def name_= (n: String) = {this.n=n}
}
Person p =new Person()
p.name //calls getter
p.name="Something" //calls setter
Voilou voili !
intéressant ! on voit quand meme que les évolutions de java 7 sont inspirées par d’autres langages de JVM. j’essayerai de faire la même comparaison pour groovy
alors j’ai un petite question :
pour les getters et setters y a t’il une maniérè de les spécifier sans avoir un lien sur le nommage qui peut être source d’erreur non détectable. Peut être même dans un nouveau bloc.
public class Person {
public String forename property{
get(…){
}
set(…){
}
};
public int ageproperty property {
get(…){
}
set(…){
}
};
}