Mendeteksi saat objek const diteruskan ke fungsi yang memutasinya, di Dart
Ambil contoh ini:
void modl(List<int> l) {
l.add(90);
print(l);
}
class Foo {
final List<int> bar;
const Foo(this.bar);
@override
String toString() => 'Foo{bar: $bar}';
}
void main() {
var foo = const Foo([1,2,3,4]);
modl(foo.bar);
print (foo);
}
Menjalankan kode di atas menghasilkan runtime Uncaught Error
, tetapi menghapus const
dari
var foo = const Foo([1,2,3,4]);
memungkinkannya bekerja.
Ini sepertinya bug bagi saya karena variabel const dapat dimutasi dan dart mendeteksi ini pada waktu proses, yang berarti ia memiliki sarana untuk mendeteksi ketika objek const diubah, tetapi seharusnya ini tidak terdeteksi pada waktu kompilasi, mengingat variabel const disebut " konstanta waktu kompilasi ".
Jika ini bukan bug, apakah ada sesuatu di dart yang memungkinkan kita mendeteksi pada waktu kompilasi ketika sebuah const
variabel mungkin akan dimutasi oleh sebuah operasi?
Di C ++, compiler error saat kita mencoba melakukan sesuatu seperti ini. Adakah yang dapat kita lakukan di Dart untuk menghindari kesalahan ini saat runtime?
Jawaban
Tidak. Dart const
adalah fitur waktu kompilasi seputar pembuatan objek, tetapi tidak tercermin dalam sistem tipe. Anda tidak dapat membedakan dari tipe objek apa pun apakah itu konstanta atau bukan.
Biasanya itu tidak menjadi masalah karena sebuah instance dari kelas yang bisa menjadi const tidak dapat dimodifikasi. Ini tidak dijamin sebagai sangat tidak dapat diubah, tetapi bidangnya sendiri tidak dapat diubah.
Daftar, set, dan peta bisa berupa konstan dan bisa berubah. Itulah yang Anda lihat di sini. Argumen daftar ke const Foo(const [1, 2, 3, 4])
tetap, meskipun Anda menghapus redundan const
pada literal daftar. Anda akan memiliki masalah yang sama dengan new Foo(const [1, 2, 3, 4])
, yang juga akan memberikan kekal foo.bar
, tetapi yang sebaliknya tidak dapat dibedakan dari new Foo([1, 2, 3, 4])
. Satu-satunya perbedaan nyata adalah apakah daftar dapat dimodifikasi atau tidak, dan satu-satunya cara untuk mendeteksinya adalah dengan mencoba memodifikasinya.
Daftar, set, dan peta tidak menyediakan cara apa pun untuk mendeteksi apakah mereka bisa berubah atau tidak kecuali mencoba, dan menangkap kesalahan.
Saat membandingkan dengan C ++, pengertian Dart tentang keberadaan const
adalah properti dari objek atau, sebenarnya, cara objek dibuat. Itu mungkin memiliki beberapa konsekuensi untuk objek tersebut. A const Foo(..)
hanya membuat Foo
objek normal , tetapi hanya dapat membuat objek yang sangat tidak berubah, dan dikanonikalisasi. A const [...]
atau const {...}
membuat jenis daftar / peta / set yang berbeda dari literal non-const, tetapi itu tidak terlihat dalam jenisnya.
Dalam C ++, being const
adalah properti dari referensi objek, dan membatasi bagaimana referensi tersebut dapat digunakan, tetapi tidak ada objek konstan seperti itu. Objek apa pun bisa dilewatkan sebagai const
referensi.
Kedua konsep ini sangat berbeda sifatnya, dan kebetulan menggunakan nama yang sama (dan keduanya juga berbeda dari JavaScript const
).