Quelle est la différence entre une définition var et val dans Scala?

Quelle est la différence entre un var et val définition de Scala et pourquoi la langue besoin des deux? Pourquoi choisiriez-vous un val sur un var et vice versa?

272
demandé sur Derek Mahar 2009-11-24 19:57:39

13 réponses

, Comme tant d'autres l'ont dit, l'objet affecté à un val ne peut pas être remplacé, et l'objet affecté à un var peut. Cependant, ledit objet peut avoir son état interne modifié. Par exemple:

class A(n: Int) {
  var value = n
}

class B(n: Int) {
  val value = new A(n)
}

object Test {
  def main(args: Array[String]) {
    val x = new B(5)
    x = new B(6) // Doesn't work, because I can't replace the object created on the line above with this new one.
    x.value = new A(6) // Doesn't work, because I can't replace the object assigned to B.value for a new one.
    x.value.value = 6 // Works, because A.value can receive a new object.
  }
}

Donc, même si nous ne pouvons pas changer l'objet assigné à x, nous pourrions changer l'état d'un objet. À la racine de celui-ci, cependant, il y avait un var.

Maintenant, l'immuabilité est une bonne chose pour de nombreuses raisons. Tout d'abord, si un objet ne change pas d'état interne, vous n'avez pas vous devez vous inquiéter si une autre partie de votre code le change. Par exemple:

x = new B(0)
f(x)
if (x.value.value == 0)
  println("f didn't do anything to x")
else
  println("f did something to x")

Cela devient particulièrement important avec les systèmes multithread. Dans un système multithread, ce qui suit peut se produire:

x = new B(1)
f(x)
if (x.value.value == 1) {
  print(x.value.value) // Can be different than 1!
}

Si vous utilisez val exclusivement, et n'utilisez que des structures de données immuables (c'est-à-dire, évitez les tableaux, tout dans scala.collection.mutable, etc.), vous pouvez être assuré que cela n'arrivera pas. Autrement dit, à moins qu'il n'y ait du code, peut-être même un framework, faire des astuces de réflexion - la réflexion peut changer les valeurs "immuables", malheureusement.

C'est une raison, mais il y en a une autre. Lorsque vous utilisez var, vous pouvez être tenté en réutilisant le même var fins multiples. Cela a quelques problèmes:

  • Il sera plus difficile pour les personnes lisant le code de savoir quelle est la valeur d'une variable dans une certaine partie du code.
  • Vous pouvez oublier de réinitialiser la variable dans un chemin de code, et finir par passer de mauvaises valeurs en aval dans le code.

En termes simples, l'utilisation de val est plus sûre et conduit à un code plus lisible.

On peut alors aller dans l'autre sens. Si val est-ce mieux, pourquoi avoir var du tout? Eh bien, certaines langues ont pris cette voie, mais il y a des situations dans lesquelles la mutabilité améliore les performances, beaucoup.

Par exemple, prenez un Queue immuable. Lorsque vous enqueue ou dequeue choses, vous obtiendrez une nouvelle Queue objet. Comment alors, iriez-vous traiter tous les éléments dans il?

Je vais passer en revue cela avec un exemple. Disons que vous avez une file d'attente de chiffres, et que vous voulez en composer un nombre. Par exemple, si j'ai une file d'attente avec 2, 1, 3, dans cet ordre, je veux revenir le numéro 213. Résolvons-le d'abord avec un mutable.Queue:

def toNum(q: scala.collection.mutable.Queue[Int]) = {
  var num = 0
  while (!q.isEmpty) {
    num *= 10
    num += q.dequeue
  }
  num
}

Ce code est rapide et facile à comprendre. Son principal inconvénient est que la file d'attente qui est passée est modifiée par toNum, Vous devez donc en faire une copie au préalable. C'est le genre de gestion d'objets qui immutabilité vous rend libre de.

Maintenant, cachons-le à un immutable.Queue:

def toNum(q: scala.collection.immutable.Queue[Int]) = {
  def recurse(qr: scala.collection.immutable.Queue[Int], num: Int): Int = {
    if (qr.isEmpty)
      num
    else {
      val (digit, newQ) = qr.dequeue
      recurse(newQ, num * 10 + digit)
    }
  }
  recurse(q, 0)
}

Parce que je ne peux pas réutiliser une variable pour garder une trace de mon num, comme dans l'exemple précédent, je dois recourir à la récursivité. Dans ce cas, il s'agit d'une récursion de queue, qui a de très bonnes performances. Mais ce n'est pas toujours le cas: parfois, il n'y a tout simplement pas de bonne solution de récursion de queue (lisible, simple).

Notez, cependant, que je peux réécrire ce code pour utiliser un immutable.Queue et a var, au même temps! Par exemple:

def toNum(q: scala.collection.immutable.Queue[Int]) = {
  var qr = q
  var num = 0
  while (!qr.isEmpty) {
    val (digit, newQ) = qr.dequeue
    num *= 10
    num += digit
    qr = newQ
  }
  num
}

Ce code est toujours efficace, ne nécessite pas de récursivité, et vous n'avez pas besoin de vous inquiéter si vous devez faire une copie de votre file d'attente ou non avant d'appeler toNum. Naturellement, j'ai évité de réutiliser des variables à d'autres fins, et aucun code en dehors de cette fonction ne les voit, donc je n'ai pas besoin de m'inquiéter de voir leurs valeurs changer d'une ligne à l'autre-sauf quand je le fais explicitement.

Scala a choisi de laisser le programmeur le faire, si le programmeur considéré comme la meilleure solution. D'autres langues ont choisi de rendre ce code difficile. Le prix payé par Scala (et tout langage avec une mutabilité généralisée) est que le compilateur n'a pas autant de marge de manœuvre dans l'optimisation du code qu'il pourrait autrement. La réponse de Java à cela est d'optimiser le code en fonction du profil d'exécution. Nous pourrions continuer et sur les avantages et les inconvénients de chaque côté.

Personnellement, je pense que Scala trouve le bon équilibre, pour l'instant. Il n'est pas parfait, et de loin. Je pense que Clojure et Haskell ont des notions très intéressantes qui ne sont pas adoptées par Scala, mais Scala a aussi ses propres forces. Nous allons voir ce qui arrive sur l'avenir.

302
répondu Daniel C. Sobral 2013-04-24 18:27:48

val est final, c'est-à-dire ne peut pas être défini. Pensez {[1] } en java.

55
répondu Jackson Davis 2009-11-24 17:23:38

, En termes simples:

Var = variable

Val = variable + final

41
répondu Ajay Gupta 2018-01-01 17:11:17

La différence est qu'un var peut être ré-attribuée alors qu'un val ne peut pas. La mutabilité, ou autrement de tout ce qui est réellement assigné, est un problème secondaire:

import collection.immutable
import collection.mutable
var m = immutable.Set("London", "Paris")
m = immutable.Set("New York") //Reassignment - I have change the "value" at m.

Considérant ce qui suit:

val n = immutable.Set("London", "Paris")
n = immutable.Set("New York") //Will not compile as n is a val.

, Et donc:

val n = mutable.Set("London", "Paris")
n = mutable.Set("New York") //Will not compile, even though the type of n is mutable.

Si vous construisez une structure de données et que tous ses champs sont val s, cette structure de données est donc immuable, car son état ne peut pas changer.

20
répondu oxbow_lakes 2013-04-24 18:30:03

val moyens immuable et var signifie mutable.

Discussion complète.

19
répondu Stefan Kendall 2009-11-24 16:58:39

Penser en termes de C++,

val x: T

Est analogue à un pointeur constant vers des données non constantes

T* const x;

Alors que

var x: T 

Est analogue à un pointeur non constant vers des données non constantes

T* x;

Favoriser val sur var augmente l'immuabilité de la base de code, ce qui peut faciliter son exactitude, sa simultanéité et sa compréhensibilité.

11
répondu Mario Galic 2015-10-16 21:04:14

" val signifie immuable et var signifie mutable."

Pour paraphraser, "val signifie valeur et var signifie variable".

Une distinction qui se trouve être extrêmement importante en informatique (parce que ces deux concepts définissent l'essence même de la programmation), et que OO a réussi à brouiller presque complètement, car dans OO, le seul axiome est que "tout est un objet". Et que, par conséquent, beaucoup de programmeurs ces jours-ci ont tendance à ne pas comprendre / apprécier / reconnaître, parce qu'ils ont été endoctrinés dans "Penser la façon OO" exclusivement. Conduisant souvent à des objets variables/mutables utilisés comme everywhere , lorsque des objets value/immuables auraient souvent été meilleurs.

8
répondu Erwin Smout 2009-11-24 17:33:53

Val signifie immuable et var signifie mutable

Vous pouvez penser {[0] } comme langage de programmation java final KEY world ou langage C++ const KEY world。

6
répondu Rollen Holt 2014-11-07 09:50:18

Un val est similaire à une variable finale en Java. Une fois initialisé, un val ne peut jamais être réaffecté.

A var , en revanche, est similaire à une variable Non finale en Java. Un var peut être réaffecté tout au long de sa durée de vie.

2
répondu Amine Sagaama 2017-01-05 22:11:34

C'est aussi simple que son nom.

Var signifie qu'il peut varier

Val signifie invariable

1
répondu user105003 2016-12-27 19:29:41

Les valeurs Val sont des constantes de stockage typées. Une fois créé, sa valeur ne peut pas être réattribuée. une nouvelle valeur peut être définie avec le mot-clé val.

Par exemple. val x: Int = 5

Ici, le type est facultatif car scala peut le déduire de la Valeur assignée.

Les variables Var sont des unités de stockage typées qui peuvent à nouveau recevoir des valeurs tant que l'espace mémoire est réservé.

Par exemple. var x: Int = 5

Les données stockées dans les deux unités de stockage sont automatiquement désallouées par JVM une fois ce ne sont plus nécessaires.

Dans scala, les valeurs sont préférées aux variables en raison de la stabilité qu'elles apportent au code, en particulier dans le code concurrent et multithread.

0
répondu SunTech 2017-03-19 16:31:42

Même Si beaucoup ont déjà répondu à la différence entre Val et var. Mais un point à noter est que val n'est pas exactement comme le mot-clé final.

Nous pouvons changer la valeur de val en utilisant la récursivité mais nous ne pouvons jamais changer la valeur de final. Final est plus constant que Val.

def factorial(num: Int): Int = {
 if(num == 0) 1
 else factorial(num - 1) * num
}

Les paramètres de la méthode sont par défaut val et à chaque valeur d'appel est en cours de modification.

0
répondu Mahesh Chand Kandpal 2018-07-18 07:38:04

Val son finale, ne réaffectés

Alors que, Var peut êtreréaffecté plus tard .

0
répondu Crime_Master_GoGo 2018-08-11 19:31:07