64 votes

Évaluation `def` vs` val` vs `lazy val` en Scala

Ai-je raison de comprendre que

  • def est évalué à chaque accès

  • lazy val est évalué dès qu'il est accédé

  • val est évalué une fois qu'il est entré dans la portée de l'exécution?

90voto

om-nom-nom Points 33691

Oui, mais il y a un bon truc: si vous avez une valeur paresseuse, et lors de la première évaluation, elle obtiendra une exception, la prochaine fois que vous essaierez d'y accéder, elle tentera de se réévaluer elle-même.

Voici un exemple:

 scala> import io.Source
import io.Source

scala> class Test {
     | lazy val foo = Source.fromFile("./bar.txt").getLines
     | }
defined class Test

scala> val baz = new Test
baz: Test = Test@ea5d87

//right now there is no bar.txt

scala> baz.foo
java.io.FileNotFoundException: ./bar.txt (No such file or directory)
    at java.io.FileInputStream.open(Native Method)
    at java.io.FileInputStream.<init>(FileInputStream.java:137)
...

// now I've created empty file named bar.txt
// class instance is the same

scala> baz.foo
res2: Iterator[String] = empty iterator
 

51voto

Owen Points 14439

Oui, bien que pour le troisième, je dirais "lorsque cette instruction est exécutée", car, par exemple:

 def foo() {
    new {
        val a: Any = sys.error("b is " + b)
        val b: Any = sys.error("a is " + a)
    }
}
 

Cela donne "b is null" . b n'est jamais évalué et son erreur n'est jamais renvoyée. Mais il entre dans le champ dès que le contrôle entre dans le bloc.

11voto

Malte Schwerhoff Points 5713

Une bonne raison pour choisir l' def sur val, surtout dans les classes abstraites (ou des caractères qui sont utilisés pour imiter Java les interfaces), est, que vous pouvez remplacer un def avec un val dans les sous-classes, mais pas l'inverse.

Concernant l' lazy, il y a deux choses que je peux voir que l'on devrait avoir à l'esprit. La première est qu' lazy introduit une certaine gestion d'exécution, mais je suppose que vous devez évaluer votre situation spécifique afin de déterminer si cette réalité a un impact significatif sur les performances d'exécution. L'autre problème avec l' lazy est qu'il peut-être des retards de lever une exception, ce qui pourrait rendre plus difficile de raisonner à propos de votre programme, car l'exception est levée pas direct, mais seulement lors de la première utilisation.

6voto

Travis Brown Points 56342

Vous êtes correct. Pour preuve de la spécification:

De "3.3.1 Types de Méthode" (pour def):

Sans paramètre méthodes nom des expressions qui sont réévalués à chaque fois la méthode sans paramètre nom est référencé.

De "4.1 les Déclarations de Valeur et de Définitions":

Une définition de la valeur val x : T = e définit x , comme le nom de la valeur qui résulte de l'évaluation de l' e.

Un paresseux définition de la valeur évalue son côté droit, e le premier fois que la valeur est accessible.

3voto

Jesper Points 65733

def définit une méthode. Lorsque vous appelez la méthode, la méthode ofcourse s'exécute.

val définit une valeur (une variable immuable). L'expression d'affectation est évaluée lorsque la valeur est initialisée.

lazy val définit une valeur avec initialisation différée. Il sera initialisé lors de sa première utilisation, donc l'expression d'affectation sera évaluée ensuite.

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