Quelqu'un peut-il expliquer les traits de Scala? Quels sont les avantages des traits par rapport à l'extension d'une classe abstraite?
La réponse courte est que vous pouvez utiliser plusieurs traits - ils sont "empilables". De plus, les traits ne peuvent pas avoir de paramètres constructeur.
Voici comment les traits sont empilés. Notez que l'ordre des traits est important. Ils s'appelleront de droite à gauche.
class Ball {
def properties(): List[String] = List()
override def toString() = "It's a" +
properties.mkString(" ", ", ", " ") +
"ball"
}
trait Red extends Ball {
override def properties() = super.properties ::: List("red")
}
trait Shiny extends Ball {
override def properties() = super.properties ::: List("shiny")
}
object Balls {
def main(args: Array[String]) {
val myBall = new Ball with Shiny with Red
println(myBall) // It's a shiny, red ball
}
}
Ce site donne un bon exemple d'utilisation des traits. Un grand avantage des traits est que vous pouvez étendre plusieurs traits mais une seule classe abstraite. Les traits résolvent de nombreux problèmes avec l'héritage multiple mais permettent la réutilisation du code.
Si vous connaissez Ruby, les traits sont similaires aux mix-ins
package ground.learning.scala.traits
/**
* Created by Mohan on 31/08/2014.
*
* Stacks are layered one top of another, when moving from Left -> Right,
* Right most will be at the top layer, and receives method call.
*/
object TraitMain {
def main(args: Array[String]) {
val strangers: List[NoEmotion] = List(
new Stranger("Ray") with NoEmotion,
new Stranger("Ray") with Bad,
new Stranger("Ray") with Good,
new Stranger("Ray") with Good with Bad,
new Stranger("Ray") with Bad with Good)
println(strangers.map(_.hi + "\n"))
}
}
trait NoEmotion {
def value: String
def hi = "I am " + value
}
trait Good extends NoEmotion {
override def hi = "I am " + value + ", It is a beautiful day!"
}
trait Bad extends NoEmotion {
override def hi = "I am " + value + ", It is a bad day!"
}
case class Stranger(value: String) {
}
Sortie: Liste (je suis Ray , Je suis Ray, c'est une mauvaise journée! , Je suis Ray, c'est une belle journée! , je suis Ray, c'est une mauvaise journée! , je suis Ray, c'est une belle journée! )
Ceci est le meilleur exemple que j'ai vu
Scala en pratique: Composer des traits - style Lego: http://gleichmann.wordpress.com/2009/10/21/scala-in-practice-composing-traits-lego-style/
class Shuttle extends Spacecraft with ControlCabin with PulseEngine{
val maxPulse = 10
def increaseSpeed = speedUp
}
Les traits sont utiles pour mélanger des fonctionnalités dans une classe. Jetez un oeil à http://scalatest.org/ . Notez comment vous pouvez mélanger dans différentes langues spécifiques au domaine (DSL) dans une classe de test. consultez le guide de démarrage rapide pour consulter certains des DSL pris en charge par Scalatest ( http://scalatest.org/quick_start )
Je cite le site Web du livre Programmation en Scala, première édition et plus précisément la section intitulée " Pour trait, ou pas pour trait? "du chapitre 12.
Chaque fois que vous implémentez une collection de comportements réutilisable, vous devrez décider si vous souhaitez utiliser un trait ou une classe abstraite. Il n'y a pas de règle ferme, mais cette section contient quelques directives à considérer.
Si le comportement ne sera pas réutilisé, faites-en une classe concrète. Ce n'est pas un comportement réutilisable après tout.
S'il peut être réutilisé dans plusieurs classes non liées, faites-en un trait. Seuls les traits peuvent être mélangés dans différentes parties de la hiérarchie des classes.
Il y a un peu plus d'informations dans le lien ci-dessus concernant les traits et je vous suggère de lire la section complète. J'espère que ça aide.
Comme pour les interfaces en Java, les traits sont utilisés pour définir les types d'objets en spécifiant la signature des méthodes prises en charge.
Contrairement à Java, Scala permet aux traits d'être partiellement implémentés; c'est-à-dire qu'il est possible de définir des implémentations par défaut pour certaines méthodes.
Contrairement aux classes, les traits peuvent ne pas avoir de paramètres constructeur. Les traits sont comme des classes, mais qui définissent une interface de fonctions et de champs que les classes peuvent fournir des valeurs et des implémentations concrètes.
Les traits peuvent hériter d'autres traits ou de classes.