SUITCASECLASS
15 Novembre 2012
Toulouse JUG
( )Didier Plaindoux @dplaindoux
INTRODUCTIONAUX"CASECLASS"DESCALA
Petite initiation basée sur:
un exemple simple de taxomonie i.e. JSon
un glissement progressif vers les case classes
Expression des termes
Décomposition structurelle
Protection du design
JAVASCRIPTOBJECTNOTATIONAKAJSON
Formalisme pour la représentation de données:
valeurs (String, Number, Boolean, Null),
tableaux et
objets
[{"name":"Scala","version":2},{"name":"Java","version":8}]
TAXONOMIEOBJET
JSonVal
JSonArray
JSonObject
JSonString
JSonExpJSonInt
JSonBool
JSonNullJSonNull
VALEUR&EXPRESSION
abstract class JSonVal {
def stringify(): String
}
abstract class JSonExp extends JSonVal
VALEURSATOMIQUES
Mutualisation de la déclaration et des paramétres
Pas de static dans les classes
JSonNull est un objet singleton
class JSonString(value: String) extends JSonVal {
def stringify(): String = '"' + value + '"' // Incomplet !
}
class JSonInt(value: Int) extends JSonVal {
def stringify(): String = String.valueOf(value)
}
class JSonBool(value: Boolean) extends JSonVal {
def stringify(): String = String.valueOf(value)
}
object JSonNull extends JSonVal {
def stringify(): String = "null"
}
TABLEAUX&OBJETS
Sequence comprehension:
for (e <- List(1,2,4,8)) yield e*2 List(2,4,8,16)
class JSonArray(elems: List[JSonVal]) extends JSonExp {
def stringify(): String = {
val l = for (e <- elems) yield e.stringify()
l.addString(new StringBuilder,"[",",","]").toString()
}
}
class JSonObject(atts: Map[String,JSonVal]) extends JSonExp {
def stringify(): String = {
val l = for ((k,v) <- atts)
yield '"' + k + '"' + ':' + v.stringify()
l.addString(new StringBuilder,"{",",","}").toString()
}
}
EXEMPLES
scala> val jsScala = new JSonObject(Map(
"name" -> new JSonString("Scala"),
"version" -> new JSonInt(2)
))
jsScala: JSonObject = JSonObject@70103
scala> val jsJava = new JSonObject(Map(
"name" -> new JSonString("Java"),
"version" -> new JSonInt(8)
))
jsJava: JSonObject = JSonObject@5425
scala> new JSonArray(List(jsScala,jsJava)).stringify()
res53: String = [{"name":"Scala","version":2},{"name":"Java", "version":8}]
CONSTAT
Approche orientée Objet:
Extension par ajout de type de donnée
Reposant sur le polymorphisme d'héritage
Compilation incrémentale vs. fonction
LESCASECLASSES
Classe à part entière
Exporte les paramètres du constructeur
Manipulable par Pattern Matching
Construction simpli ée sans new explicite
VALEURS&EXPRESSIONS
abstract class JSonVal
abstract class JSonExp extends JSonVal
case class JSonString(value: String) extends JSonVal
case class JSonInt(value: Int) extends JSonVal
case class JSonBool(value: Boolean) extends JSonVal
case object JSonNull extends JSonVal
case class JSonArray(elems: List[JSonVal]) extends JSonExp
case class JSonObject(atts: Map[String,JSonVal]) extends JSonExp
LESNEWENMOINS...
scala> val jsScala = JSonObject(Map(
"name" -> JSonString("Scala"),
"version" -> JSonInt(2)
))
jsScala: JSonObject = JSonObject@70103
scala> val jsJava = JSonObject(Map(
"name" -> JSonString("Java"),
"version" -> JSonInt(8)
))
jsJava: JSonObject = JSonObject@5425
TRANSFORMATIONENCHAÎNEDECARACTÈRES
def stringify(value:JSonVal): String =
value match {
case JSonString(s) => '"' + s + '"'
case JSonInt(i) => String.valueOf(i)
case JSonBool(b) => String.valueOf(b)
case JSonNull => "null"
case JSonArray(elems) => {
val l = for (e <- elems) yield stringify(e)
l.addString(new StringBuilder,"[",",","]").toString()
}
case JSonObject(atts) => {
val l = for ((k,v) <- atts)
yield '"' + k + '"' + ':' + stringify(v)
l.addString(new StringBuilder,"{",",","}").toString()
}
}
DÉFINITIONPARTIELLE
Extension à postériori
Perte de la consistance des méthodes
object JSonFoo extends JSonVal
scala> stringify(JSonFoo)
scala.MatchError: JSonFoo (of class JSonFoo$)
...
PRÉVENIRPLUTÔTQUEGUÉRIR-ACTE1
Limitation de l'extension directe via sealed
Uniquement dans l'unité de compilation ( chier)
Déclaration non transitive
sealed abstract class JSonVal
sealed abstract class JSonExp extends JSonVal
final case class JSonString(value: String) extends JSonVal
final case class JSonArray(elems: List[JSonVal]) extends JSonExp
...
PRÉVENIRPLUTÔTQUEGUÉRIR-ACTE2
Véri cation à la compilation
Exhaustivité du pattern matching et sealed type
scala> def stringify(value:JSonVal): String =
value match {
...
// cas JSonNull non couvert
}
warning: match is not exhaustive!
missing combination JSonNull
value match {
^
stringify: (value: JSonVal)String
CONSTAT
Approche fonctionnelle:
Extension par ajout de fonctions
Repose sur la reconnaissance de termes
Compilation incrémentale vs. données
POURFINIR
Explorer plus en avant les case classes
Pattern matching plus sélectif
Cas de l'extension de case classes !
Dé nition des extracteurs
Approche Orientée Objet et Pattern Matching
Méthode de classe et Pattern Matching
"Expression Problem" de Philip Wadler

Suit case class

  • 1.
    SUITCASECLASS 15 Novembre 2012 ToulouseJUG ( )Didier Plaindoux @dplaindoux
  • 2.
    INTRODUCTIONAUX"CASECLASS"DESCALA Petite initiation baséesur: un exemple simple de taxomonie i.e. JSon un glissement progressif vers les case classes Expression des termes Décomposition structurelle Protection du design
  • 3.
    JAVASCRIPTOBJECTNOTATIONAKAJSON Formalisme pour lareprésentation de données: valeurs (String, Number, Boolean, Null), tableaux et objets [{"name":"Scala","version":2},{"name":"Java","version":8}]
  • 4.
  • 5.
    VALEUR&EXPRESSION abstract class JSonVal{ def stringify(): String } abstract class JSonExp extends JSonVal
  • 6.
    VALEURSATOMIQUES Mutualisation de ladéclaration et des paramétres Pas de static dans les classes JSonNull est un objet singleton class JSonString(value: String) extends JSonVal { def stringify(): String = '"' + value + '"' // Incomplet ! } class JSonInt(value: Int) extends JSonVal { def stringify(): String = String.valueOf(value) } class JSonBool(value: Boolean) extends JSonVal { def stringify(): String = String.valueOf(value) } object JSonNull extends JSonVal { def stringify(): String = "null" }
  • 7.
    TABLEAUX&OBJETS Sequence comprehension: for (e<- List(1,2,4,8)) yield e*2 List(2,4,8,16) class JSonArray(elems: List[JSonVal]) extends JSonExp { def stringify(): String = { val l = for (e <- elems) yield e.stringify() l.addString(new StringBuilder,"[",",","]").toString() } } class JSonObject(atts: Map[String,JSonVal]) extends JSonExp { def stringify(): String = { val l = for ((k,v) <- atts) yield '"' + k + '"' + ':' + v.stringify() l.addString(new StringBuilder,"{",",","}").toString() } }
  • 8.
    EXEMPLES scala> val jsScala= new JSonObject(Map( "name" -> new JSonString("Scala"), "version" -> new JSonInt(2) )) jsScala: JSonObject = JSonObject@70103 scala> val jsJava = new JSonObject(Map( "name" -> new JSonString("Java"), "version" -> new JSonInt(8) )) jsJava: JSonObject = JSonObject@5425 scala> new JSonArray(List(jsScala,jsJava)).stringify() res53: String = [{"name":"Scala","version":2},{"name":"Java", "version":8}]
  • 9.
    CONSTAT Approche orientée Objet: Extensionpar ajout de type de donnée Reposant sur le polymorphisme d'héritage Compilation incrémentale vs. fonction
  • 10.
    LESCASECLASSES Classe à partentière Exporte les paramètres du constructeur Manipulable par Pattern Matching Construction simpli ée sans new explicite
  • 11.
    VALEURS&EXPRESSIONS abstract class JSonVal abstractclass JSonExp extends JSonVal case class JSonString(value: String) extends JSonVal case class JSonInt(value: Int) extends JSonVal case class JSonBool(value: Boolean) extends JSonVal case object JSonNull extends JSonVal case class JSonArray(elems: List[JSonVal]) extends JSonExp case class JSonObject(atts: Map[String,JSonVal]) extends JSonExp
  • 12.
    LESNEWENMOINS... scala> val jsScala= JSonObject(Map( "name" -> JSonString("Scala"), "version" -> JSonInt(2) )) jsScala: JSonObject = JSonObject@70103 scala> val jsJava = JSonObject(Map( "name" -> JSonString("Java"), "version" -> JSonInt(8) )) jsJava: JSonObject = JSonObject@5425
  • 13.
    TRANSFORMATIONENCHAÎNEDECARACTÈRES def stringify(value:JSonVal): String= value match { case JSonString(s) => '"' + s + '"' case JSonInt(i) => String.valueOf(i) case JSonBool(b) => String.valueOf(b) case JSonNull => "null" case JSonArray(elems) => { val l = for (e <- elems) yield stringify(e) l.addString(new StringBuilder,"[",",","]").toString() } case JSonObject(atts) => { val l = for ((k,v) <- atts) yield '"' + k + '"' + ':' + stringify(v) l.addString(new StringBuilder,"{",",","}").toString() } }
  • 14.
    DÉFINITIONPARTIELLE Extension à postériori Pertede la consistance des méthodes object JSonFoo extends JSonVal scala> stringify(JSonFoo) scala.MatchError: JSonFoo (of class JSonFoo$) ...
  • 15.
    PRÉVENIRPLUTÔTQUEGUÉRIR-ACTE1 Limitation de l'extensiondirecte via sealed Uniquement dans l'unité de compilation ( chier) Déclaration non transitive sealed abstract class JSonVal sealed abstract class JSonExp extends JSonVal final case class JSonString(value: String) extends JSonVal final case class JSonArray(elems: List[JSonVal]) extends JSonExp ...
  • 16.
    PRÉVENIRPLUTÔTQUEGUÉRIR-ACTE2 Véri cation àla compilation Exhaustivité du pattern matching et sealed type scala> def stringify(value:JSonVal): String = value match { ... // cas JSonNull non couvert } warning: match is not exhaustive! missing combination JSonNull value match { ^ stringify: (value: JSonVal)String
  • 17.
    CONSTAT Approche fonctionnelle: Extension parajout de fonctions Repose sur la reconnaissance de termes Compilation incrémentale vs. données
  • 18.
    POURFINIR Explorer plus enavant les case classes Pattern matching plus sélectif Cas de l'extension de case classes ! Dé nition des extracteurs Approche Orientée Objet et Pattern Matching Méthode de classe et Pattern Matching "Expression Problem" de Philip Wadler