79 votes

Mixins vs composition en scala

Dans le monde java (plus précisément si vous n'avez pas l'héritage multiple/mixin) la règle de base est assez simple: "le Profit de l'objet de la composition au cours de l'héritage de classe".

J'aimerais savoir si et comment il est changé si vous aussi vous envisagez de mixin, en particulier dans les scala?
Sont mixin considéré comme un moyen de l'héritage multiple, ou plus de la composition de classe?
Est-il aussi un "en Faveur de l'objet de la composition au cours de la composition de classe" (ou l'inverse) la directive?

J'ai vu assez quelques exemples lorsque les gens utilisent (ou l'abus) mixin lors de la composition d'objet pourrait aussi faire le travail et je ne suis pas toujours sûr que l'on est mieux. Il me semble que vous pouvez réaliser tout à fait les mêmes choses avec eux, mais il ya quelques différences aussi, quelques exemples:

  • visibilité - avec mixin tout devient une partie de l'api publique, ce qui n'est pas le cas avec la composition.
  • verbosité - dans la plupart des cas mixin sont moins détaillées et un peu plus facile à utiliser, mais il n'est pas toujours le cas (par exemple si vous aussi vous utilisez des types de hiérarchies complexes)

Je sais que la réponse est "Ça dépend", mais il y a probablement certains situation typique lorsque ceci ou cela, c'est mieux.

Quelques exemples de lignes directrices j'ai pu arriver jusqu'ici (en supposant que j'ai deux traits A et B et Un veut utiliser certaines méthodes de B):

  • Si vous voulez prolonger l'API de Un avec les méthodes de B puis mixin, sinon la composition. Mais cela n'aide pas si la classe/instance que je suis de la création ne fait pas partie d'une API publique.
  • Si vous souhaitez utiliser certains des motifs qui ont besoin de mixin (par exemple, Empilable Trait Motif) ensuite c'est une décision facile à prendre.
  • Si vous avez des dépendances circulaires puis mixin avec l'auto types peuvent aider. (J'essaie d'éviter cette situation, mais il n'est pas toujours facile)
  • Si vous voulez un peu de dynamique, d'exécution des décisions de façon de faire, puis la composition objet de la composition.

Dans de nombreux cas, mixin semble plus facile (et/ou moins détaillé), mais je suis tout à fait sûr qu'ils ont aussi quelques pièges, comme le "Dieu de la classe" et d'autres ont décrit en deux artima articles: partie 1, partie 2 (d'ailleurs il me semble que la plupart des autres problèmes ne sont pas pertinents ou pas si grave pour la scala).

Vous avez d'autres astuces comme celle-ci?

41voto

Dave Griffith Points 12923

Beaucoup de problèmes que les gens ont avec mix-ins peuvent être évités en Scala si vous ne mélange dans l'abrégé des traits dans vos définitions de classe, puis mélanger dans le béton traits à l'instanciation d'objets temps. Par exemple

trait Locking{
   // abstract locking trait, many possible definitions
   protected def lock(body: =>A):A
}

class MyService{
   this:Locking =>
}

//For this time, we'll use a java.util.concurrent lock
val myService:MyService = new MyService with JDK15Locking 

Ce concept a plusieurs choses à la recommander. Tout d'abord, il empêche il d'être une explosion de classes différentes combinaisons de trait fonctionnalités sont nécessaires. Deuxièmement, il permet de tester facilement, comme on peut créer et mix-in "ne rien faire" béton traits, semblables à des objets fantaisie. Enfin, nous avons complètement caché le verrouillage de trait utilisé, et même que le verrouillage est en cours, de la part de consommateurs de notre service.

Depuis que nous avons obtenu passé la plupart de la revendiquée inconvénients de mix-ins, nous sommes toujours à gauche avec un compromis entre mix-in et de la composition. Pour moi, j'ai l'habitude de prendre la décision de savoir si l'hypothétique délégué objet serait entièrement encapsulé par le contenant de l'objet, ou s'il peut potentiellement être partagés et ont un cycle de vie propre. Verrouillage fournit un bon exemple de entièrement encapsulé délégués. Si votre classe utilise un verrouillage de l'objet de gérer les accès simultanés à son état interne, le verrou est entièrement contrôlé par l'objet contenant, et ni lui, ni ses opérations sont annoncés dans le cadre des classes de l'interface publique. Entièrement encapsulé fonctionnalité de ce genre, je aller avec mix-ins. Pour quelque chose de partagé, comme une source de données, utilisez la composition.

11voto

VonC Points 414372

D'autres différences que vous n'avez pas mentionné:

  • Trait classes n'ont aucune existence indépendante:

(Programmation Scala)

Si vous trouvez qu'un trait particulier est le plus souvent utilisé en tant que parent d'autres classes, de sorte que les enfants des classes de se comporter en tant que parent trait, puis envisager de définir le trait comme une classe à la place, pour faire de cette relation logique plus clair.
(Nous avons dit se comporte comme d'habitude, plutôt que de un, parce que la première est la définition plus précise de l'héritage, basé sur le Principe de Substitution de Liskov - voir [Martin2003], par exemple.)

[Martin2003]: Robert C. Martin, Agile de Développement Logiciel: Principes, Modèles et Pratiques, Prentice Hall, 2003

  • mixin (trait) n'ont pas de paramètres du constructeur.

D'où les conseils, toujours à partir de la Programmation Scala:

Éviter de béton champs dans les traits qui ne peuvent pas être initialisés à des valeurs par défaut.
Utilisez le résumé au lieu ou à convertir le trait à une classe avec un constructeur.
Bien sûr, les apatrides, les traits ne pas avoir de problèmes avec l'initialisation.

C'est un principe général de bonne conception orientée objet qu'une instance doit toujours être dans un état valide à partir du moment où le processus de construction finitions.

La dernière partie, quant à l' initiale de l'état d'un objet, a souvent contribué à décider entre la classe (et la composition de classe) et de trait (et mixin) pour un concept donné.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X