Comment définir un var / val local dans le constructeur principal de Scala?

Dans Scala, le constructeur principal d’une classe n’a pas de corps explicite, mais est défini implicitement par le corps de la classe. Comment, alors, fait-on la distinction entre les champs et les valeurs locales (valeurs locales à la méthode constructeur)?

Par exemple, prenez l’extrait de code suivant, une forme modifiée d’un exemple de code de “Programming in Scala”:

class R(n: Int, d: Int) { private val g = myfunc val x = n / g val y = d / g } 

Ma compréhension est que cela va générer une classe avec trois champs: un privé “g”, et public “x” et “y”. Cependant, la valeur g est utilisée uniquement pour le calcul des champs x et y et n’a aucune signification au-delà de la scope du constructeur.

Donc, dans cet exemple (certes artificiel), comment définissez-vous les valeurs locales pour ce constructeur?

Par exemple

 class R(n: Int, d: Int) { val (x, y) = { val g = myfunc (n/g, d/g) } } 

Il y a plusieurs façons de le faire. Vous pouvez déclarer ces variables temporaires dans des définitions privées, à utiliser pendant la construction. Vous pouvez utiliser des variables temporaires dans des blocs qui renvoient des expressions (comme dans la réponse d’Alaz). Ou, enfin, vous pouvez utiliser de telles variables dans des constructeurs alternatifs.

D’une manière similaire aux autres constructeurs, vous pouvez également les définir dans la méthode “apply” du compagnon d’object.

Ce que vous ne pouvez pas faire, c’est déclarer un champ “temporaire”.

Notez également que tout paramètre reçu par le constructeur principal est également un champ. Si vous ne voulez pas que de tels parameters deviennent des champs et que vous ne voulez pas exposer les champs réels dans un constructeur, la solution habituelle consiste à rendre le constructeur principal privé, avec les champs réels, et à utiliser un constructeur alternatif ou un constructeur. compagnon d’object apply () comme constructeur “primaire” efficace.

Une autre option est de rendre le constructeur d’object primaire privé et d’utiliser la méthode d’application d’un object compagnon en tant que générateur. Si nous appliquons (le jeu de mots n’est pas prévu) cette approche de votre exemple, cela ressemblera à ceci:

 class R private (val x: Int, val y: Int); object R { def apply(n: Int, d: Int): R = { val g = myfunc; new R(n / g, d / g); } } 

Pour créer une instance R au lieu de:

 val r = new R(1, 2); 

écrire:

 val r = R(1, 2); 

C’est un peu verbeux, mais ça pourrait être pire, je pense :). Espérons que les valeurs privées [this] seront traitées comme des variables temporaires dans les futures versions de Scala. Martin lui-même l’a laissé entendre.

Une discussion sur ce sujet, y compris les commentaires de Martin Odersky, est ici