web-dev-qa-db-fra.com

val-mutable contre var-immutable dans Scala

Existe-t-il des directives dans Scala sur le moment d'utiliser val avec une collection mutable par rapport à l'utilisation de var avec une collection immuable? Ou devriez-vous vraiment viser val avec une collection immuable?

Le fait qu'il existe deux types de collection me donne beaucoup de choix, et souvent je ne sais pas comment faire ce choix.

94
James McCabe

Question assez courante, celle-ci. La difficulté est de trouver les doublons.

Vous devez vous efforcer de transparence référentielle. Cela signifie que, si j'ai une expression "e", je pourrais faire un val x = e, et remplacez e par x. C'est la propriété de la rupture de la mutabilité. Chaque fois que vous devez prendre une décision de conception, maximisez la transparence référentielle.

En pratique, une méthode locale var est la var la plus sûre qui existe, car elle n'échappe pas à la méthode. Si la méthode est courte, c'est encore mieux. Si ce n'est pas le cas, essayez de le réduire en extrayant d'autres méthodes.

D'un autre côté, une collection mutable a le potentiel pour s'échapper, même si ce n'est pas le cas. Lors de la modification du code, vous souhaiterez peut-être le transmettre à d'autres méthodes ou le renvoyer. C'est le genre de chose qui brise la transparence référentielle.

Sur un objet (un champ), à peu près la même chose se produit, mais avec des conséquences plus désastreuses. Dans tous les cas, l'objet aura un état et, par conséquent, rompra la transparence référentielle. Mais avoir une collection mutable signifie que même l'objet lui-même peut perdre le contrôle de qui le change.

99
Daniel C. Sobral

Si vous travaillez avec des collections immuables et que vous devez les "modifier", par exemple, y ajouter des éléments en boucle, vous devez utiliser vars car vous devez stocker la collection résultante quelque part. Si vous lisez uniquement à partir de collections immuables, utilisez vals.

En général, assurez-vous de ne pas confondre références et objets. vals sont des références immuables (pointeurs constants en C). Autrement dit, lorsque vous utilisez val x = new MutableFoo(), vous serez en mesure pour changer l'objet vers lequel x pointe, mais vous ne pourrez pas pour changer à quel objetx points. L'inverse est vrai si vous utilisez var x = new ImmutableFoo(). Reprenant mon premier conseil: si vous n'avez pas besoin de changer à quel objet un point de référence, utilisez vals.

17
Malte Schwerhoff

La meilleure façon de répondre à cela est avec un exemple. Supposons que nous ayons un processus qui collecte simplement des chiffres pour une raison quelconque. Nous souhaitons enregistrer ces numéros et enverrons la collection à n autre processus pour ce faire.

Bien sûr, nous collectons toujours des numéros après avoir envoyé la collecte à l'enregistreur. Et disons qu'il y a des frais généraux dans le processus de journalisation qui retardent la journalisation réelle. J'espère que vous pourrez voir où cela va.

Si nous stockons cette collection dans un val, (mutable parce que nous y ajoutons continuellement) mutable, cela signifie que le processus effectuant la journalisation examinera le même objet qui est toujours mis à jour par notre processus de collecte. Cette collection peut être mise à jour à tout moment, et donc quand il est temps de se connecter, nous ne pouvons pas réellement enregistrer la collection que nous avons envoyée.

Si nous utilisons un var immuable, nous envoyons une structure de données immuable à l'enregistreur. Lorsque nous ajoutons plus de nombres à notre collection, nous allons remplacer notre var par un nouvelle structure de données immuable. Cela ne signifie pas que la collection envoyée à l'enregistreur est remplacée! Il fait toujours référence à la collection qui lui a été envoyée. Notre enregistreur enregistrera donc la collection qu'il a reçue.

9
jmazin

Je pense que les exemples de ce blog apporteront plus de lumière, car la question du combo à utiliser devient encore plus importante dans les scénarios de concurrence: importance de l'immuabilité pour la concurrence . Et pendant que nous y sommes, notez l'utilisation préférée de synchronisé vs @volatile vs quelque chose comme AtomicReference: trois outils

1
Bogdan Nicolau