Früher habe ich das gedacht private val
und private final val
bin es auch, bis ich Abschnitt 4.1 in Scala Reference sah:
Eine konstante Wertedefinition hat die Form
final val x = e
wobei e ein konstanter Ausdruck ist (§6.24). Der letzte Modifikator muss vorhanden sein und es dürfen keine Typanmerkungen angegeben werden. Verweise auf den konstanten Wert x werden selbst als konstante Ausdrücke behandelt; im generierten Code werden sie durch die rechte Seite der Definition ersetzt. e.
Und ich habe einen Test geschrieben:
class PrivateVal {
private val privateVal = 0
def testPrivateVal = privateVal
private final val privateFinalVal = 1
def testPrivateFinalVal = privateFinalVal
}
javap -c
Ausgabe:
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
}
Der Bytecode ist genau so, wie Scala Reference sagte: private val
nicht private final val
.
Warum behandelt Scalac nicht einfach private val
so private final val
? Gibt es einen Grund dafür?
val
bereits unveränderlich ist, warum brauchen wir dasfinal
Schlüsselwort überhaupt in Scala? Warum kann der Compiler nicht alleval
s genauso behandeln wiefinal val
s?private
Bereichsmodifikator dieselbe Semantik wiepackage private
in Java hat. Sie können sagenprivate[this]
.private
bedeutet, dass es nur für Instanzen dieser Klasse sichtbar ist,private[this]
nur für diese Instanz - mit Ausnahme von Instanzen derselben Klasse kannprivate
niemand (einschließlich aus demselben Paket) auf den Wert zugreifen.Antworten:
Dies ist also nur eine Vermutung, aber es war in Java immer wieder ärgerlich, dass endgültige statische Variablen mit einem Literal auf der rechten Seite als Konstanten in Bytecode eingefügt werden. Dies führt zwar zu einem Leistungsvorteil, führt jedoch dazu, dass die binäre Kompatibilität der Definition unterbrochen wird, wenn sich die "Konstante" jemals ändert. Bei der Definition einer endgültigen statischen Variablen, deren Wert möglicherweise geändert werden muss, müssen Java-Programmierer auf Hacks wie das Initialisieren des Werts mit einer Methode oder einem Konstruktor zurückgreifen.
Ein Wert in Scala ist im Java-Sinne bereits endgültig. Es sieht so aus, als würden die Designer von Scala den redundanten Modifikator final verwenden, um "Erlaubnis zum Inline des konstanten Werts" zu bedeuten. Scala-Programmierer haben also die vollständige Kontrolle über dieses Verhalten, ohne auf Hacks zurückgreifen zu müssen: Wenn sie eine Inline-Konstante wünschen, einen Wert, der sich nie ändern sollte, aber schnell ist, schreiben sie "final val". Wenn sie Flexibilität wünschen, um den Wert zu ändern, ohne die Binärkompatibilität zu beeinträchtigen, einfach "val".
quelle
private val
zuprivate final val
?val
in Ihrem zweiten Absatz?Ich denke, die Verwirrung hier entsteht durch die Verschmelzung von Unveränderlichkeit mit der Semantik von final.
val
s kann in untergeordneten Klassen überschrieben werden und kann daher nicht als endgültig behandelt werden, es sei denn, dies ist ausdrücklich als solches gekennzeichnet.@Brian Die REPL bietet Klassenbereich auf Zeilenebene. Sehen:
quelle
private val
. Kann es überschrieben werden?