Saya dulu berpikir begitu private val
dan private final val
sama, sampai saya melihat bagian 4.1 di Referensi Scala:
Definisi nilai konstan adalah dari bentuknya
final val x = e
di mana e adalah ekspresi konstan (§6.24). Pengubah terakhir harus ada dan tidak ada anotasi jenis yang dapat diberikan. Referensi ke nilai konstanta x sendiri diperlakukan sebagai ekspresi konstan; dalam kode yang dihasilkan, mereka digantikan oleh sisi kanan definisi e.
Dan saya telah menulis tes:
class PrivateVal {
private val privateVal = 0
def testPrivateVal = privateVal
private final val privateFinalVal = 1
def testPrivateFinalVal = privateFinalVal
}
javap -c
keluaran:
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
}
Kode byte seperti yang dikatakan Referensi Scala: private val
bukan private final val
.
Mengapa tidak scalac hanya memperlakukan private val
sebagai private final val
? Apakah ada alasan yang mendasarinya?
val
sudah tidak dapat diubah, mengapa kita membutuhkanfinal
kata kunci sama sekali di Scala? Mengapa kompilator tidak bisa memperlakukan semuaval
dengan cara yang sama sepertifinal val
s?private
pengubah cakupan memiliki semantik yang sama sepertipackage private
di Java. Anda mungkin bermaksud mengatakanprivate[this]
.private
maksudnya itu hanya terlihat untuk instance kelas ini,private[this]
hanya instance ini - kecuali untuk instance dari kelas yang sama ,private
tidak mengizinkan siapa pun (termasuk dari paket yang sama) untuk mengakses nilai.Jawaban:
Jadi, ini hanya tebakan, tapi itu adalah gangguan abadi di Java bahwa variabel statis terakhir dengan literal di sisi kanan masuk ke bytecode sebagai konstanta. Hal itu membuat manfaat kinerja pasti, tetapi itu menyebabkan kompatibilitas biner dari definisi rusak jika "konstanta" pernah berubah. Saat menentukan variabel statis final yang nilainya mungkin perlu diubah, programmer Java harus menggunakan peretasan seperti menginisialisasi nilai dengan metode atau konstruktor.
Val di Scala sudah final dalam pengertian Java. Sepertinya desainer Scala menggunakan final pengubah redundan yang berarti "izin untuk menyebariskan nilai konstan". Jadi pemrogram Scala memiliki kendali penuh atas perilaku ini tanpa menggunakan peretasan: jika mereka menginginkan konstanta sebaris, nilai yang seharusnya tidak pernah berubah tetapi cepat, mereka menulis "nilai akhir". jika mereka menginginkan fleksibilitas untuk mengubah nilai tanpa merusak kompatibilitas biner, cukup "val".
sumber
private val
keprivate final val
?val
di paragraf kedua?Saya pikir kebingungan di sini muncul dari penggabungan kekekalan dengan semantik final.
val
s dapat diganti dalam kelas anak dan oleh karena itu tidak dapat diperlakukan sebagai final kecuali ditandai secara eksplisit.@ Brian REPL menyediakan ruang lingkup kelas pada tingkat baris. Lihat:
sumber
private val
. Bisakah itu diganti?