J'avais l'habitude de penser cela private val
et private final val
c'est pareil, jusqu'à ce que j'aie vu la section 4.1 dans Scala Reference:
Une définition de valeur constante est de la forme
final val x = e
où e est une expression constante (§6.24). Le modificateur final doit être présent et aucune annotation de type ne peut être donnée. Les références à la valeur constante x sont elles-mêmes traitées comme des expressions constantes; dans le code généré, ils sont remplacés par le côté droit de la définition e.
Et j'ai écrit un test:
class PrivateVal {
private val privateVal = 0
def testPrivateVal = privateVal
private final val privateFinalVal = 1
def testPrivateFinalVal = privateFinalVal
}
javap -c
production:
Compiled from "PrivateVal.scala"
public class PrivateVal {
public int testPrivateVal();
Code:
0: aload_0
1: invokespecial #19 // Method privateVal:()I
4: ireturn
public int testPrivateFinalVal();
Code:
0: iconst_1
1: ireturn
public PrivateVal();
Code:
0: aload_0
1: invokespecial #24 // Method java/lang/Object."<init>":()V
4: aload_0
5: iconst_0
6: putfield #14 // Field privateVal:I
9: return
}
Le code d'octet est exactement comme l'a dit Scala Reference: private val
n'est pas private final val
.
Pourquoi le scalac ne traite- t-il pas simplement private val
comme private final val
? Y a-t-il une raison sous-jacente?
val
est déjà immuable, pourquoi avons-nous besoin dufinal
mot - clé dans Scala? Pourquoi le compilateur ne peut-il pas traiter tous lesval
s de la même manière que lesfinal val
s?private
modificateur de portée a la même sémantique qu'enpackage private
Java. Vous voulez peut-être direprivate[this]
.private
signifie qu'il n'est visible que pour les instances de cette classe,private[this]
seule cette instance - à l'exception des instances de la même classe ,private
ne permet à personne (inclure du même package) d'accéder à la valeur.Réponses:
Donc, ce n'est qu'une supposition, mais c'était un ennui éternel en Java que les variables statiques finales avec un littéral sur le côté droit soient incorporées dans le bytecode en tant que constantes. Cela engendre un avantage de performance certain, mais cela provoque la rupture de la compatibilité binaire de la définition si la «constante» a changé. Lors de la définition d'une variable statique finale dont la valeur peut avoir besoin de changer, les programmeurs Java doivent recourir à des hacks comme l'initialisation de la valeur avec une méthode ou un constructeur.
Un val en Scala est déjà définitif au sens Java. Il semble que les concepteurs de Scala utilisent le modificateur redondant final pour signifier "l'autorisation d'insérer la valeur constante". Les programmeurs Scala ont donc un contrôle total sur ce comportement sans recourir à des hacks: s'ils veulent une constante inline, une valeur qui ne devrait jamais changer mais qui est rapide, ils écrivent "final val". s'ils veulent la flexibilité de changer la valeur sans casser la compatibilité binaire, juste "val".
la source
private val
àprivate final val
?val
dans votre deuxième paragraphe?Je pense que la confusion provient ici de la fusion de l'immuabilité avec la sémantique de final.
val
s peuvent être surchargés dans les classes enfants et ne peuvent donc pas être traités comme définitifs à moins d'être marqués explicitement comme tels.@Brian Le REPL fournit une portée de classe au niveau ligne. Voir:
la source
private val
. Peut-il être annulé?