Solía pensar eso private val
y private final val
son lo mismo, hasta que vi la sección 4.1 en Scala Reference:
Una definición de valor constante tiene la forma
final val x = e
donde e es una expresión constante (§6.24). El modificador final debe estar presente y no se puede dar ninguna anotación de tipo. Las referencias al valor constante x se tratan en sí mismas como expresiones constantes; en el código generado se reemplazan por el lado derecho de la definición e.
Y he escrito una prueba:
class PrivateVal {
private val privateVal = 0
def testPrivateVal = privateVal
private final val privateFinalVal = 1
def testPrivateFinalVal = privateFinalVal
}
javap -c
salida:
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
}
El código de bytes es tal como lo dijo Scala Reference: private val
no lo es private final val
.
¿Por qué scalac no trata simplemente private val
como private final val
? ¿Existe alguna razón subyacente?
val
ya es inmutable, ¿por qué necesitamos lafinal
palabra clave en Scala? ¿Por qué el compilador no puede tratar todos los correos electrónicos deval
la misma manera quefinal val
los correos electrónicos?private
modificador de alcance tiene la misma semántica quepackage private
en Java. Puede querer decirprivate[this]
.private
significa que solo es visible para instancias de esta clase,private[this]
solo esta instancia, excepto para instancias de la misma clase ,private
no permite que nadie (incluido del mismo paquete) acceda al valor.Respuestas:
Entonces, esto es solo una suposición, pero fue una molestia constante en Java que las variables estáticas finales con un literal en el lado derecho se incluyan en el código de bytes como constantes. Eso engendra un beneficio de rendimiento seguro, pero hace que la compatibilidad binaria de la definición se rompa si la "constante" alguna vez cambia. Al definir una variable estática final cuyo valor podría necesitar cambiar, los programadores de Java tienen que recurrir a trucos como inicializar el valor con un método o constructor.
Un val en Scala ya es final en el sentido de Java. Parece que los diseñadores de Scala están usando el modificador redundante final para significar "permiso para incorporar el valor constante". Así que los programadores de Scala tienen control total sobre este comportamiento sin recurrir a hacks: si quieren una constante en línea, un valor que nunca debería cambiar pero que es rápido, escriben "final val". si quieren flexibilidad para cambiar el valor sin romper la compatibilidad binaria, simplemente "val".
fuente
private val
aprivate final val
?val
en su segundo párrafo?Creo que la confusión aquí surge al combinar la inmutabilidad con la semántica de final.
val
s se pueden anular en clases secundarias y, por lo tanto, no se pueden tratar como finales a menos que se marquen explícitamente como tales.@Brian El REPL proporciona un alcance de clase a nivel de línea. Ver:
fuente
private val
. ¿Se puede anular?