Phát hiện khi một đối tượng const được truyền cho một hàm làm thay đổi nó, trong Dart
Lấy ví dụ sau:
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);
}
Chạy đoạn mã trên dẫn đến thời gian chạy Uncaught Error , nhưng loại bỏ consttừ
var foo = const Foo([1,2,3,4]);
cho phép nó hoạt động.
Điều này có vẻ như là một lỗi đối với tôi vì biến const có thể bị đột biến và dart phát hiện điều này trong thời gian chạy, có nghĩa là nó có phương tiện để phát hiện khi một đối tượng const được sửa đổi, nhưng điều này không nên được phát hiện tại thời điểm biên dịch, như Các biến const được gọi là " hằng số thời gian biên dịch ".
Nếu đây không phải là lỗi, thì có điều gì trong phi tiêu cho phép chúng tôi phát hiện tại thời điểm biên dịch khi một constbiến có thể bị đột biến bởi một hoạt động không?
Trong C ++, trình biên dịch sẽ xảy ra lỗi khi chúng ta cố gắng làm điều gì đó như thế này. Có điều gì chúng ta có thể làm trong Dart để tránh gặp phải lỗi này trong thời gian chạy không?
Trả lời
Không. Dart constlà một tính năng thời gian biên dịch xung quanh việc tạo đối tượng, nhưng nó không được phản ánh trong hệ thống kiểu. Bạn không thể biết từ loại của bất kỳ đối tượng nào liệu nó có phải là hằng số hay không.
Thông thường đó không phải là vấn đề vì một thể hiện của lớp có thể là const thì không thể thay đổi được. Nó không được đảm bảo là không thay đổi sâu sắc, nhưng bản thân cá thể không thể thay đổi các trường của nó.
Danh sách, tập hợp và bản đồ đều có thể không đổi và có thể thay đổi. Đó là những gì bạn đang thấy ở đây. Đối số danh sách const Foo(const [1, 2, 3, 4])là không đổi, ngay cả khi bạn loại bỏ phần dư thừa consttrên danh sách theo nghĩa đen. Bạn sẽ gặp vấn đề tương tự với new Foo(const [1, 2, 3, 4]), điều này cũng sẽ cung cấp một bất biến foo.bar, nhưng nếu không sẽ không thể phân biệt được new Foo([1, 2, 3, 4]). Sự khác biệt thực sự duy nhất là liệu danh sách có thể sửa đổi được hay không và cách duy nhất để phát hiện điều đó là cố gắng sửa đổi nó.
Danh sách, tập hợp và bản đồ không cung cấp bất kỳ cách nào để phát hiện xem chúng có thể thay đổi được hay không ngoại trừ việc thử và bắt lỗi.
Khi so sánh với C ++, ý niệm của Dart về bản thể constlà một thuộc tính của đối tượng hoặc thực sự là cách đối tượng được tạo ra. Điều đó có thể gây ra một số hậu quả cho đối tượng. A const Foo(..)chỉ tạo một Foođối tượng bình thường , nhưng nó chỉ có thể tạo ra các đối tượng bất biến sâu và chúng được chuẩn hóa. A const [...]hoặc const {...}tạo một loại danh sách / bản đồ / tập hợp khác với từ không phải const, nhưng nó không hiển thị trong loại.
Trong C ++, being constlà một thuộc tính của một tham chiếu đối tượng và nó hạn chế cách sử dụng tham chiếu đó, nhưng không có đối tượng hằng số nào như vậy. Bất kỳ đối tượng nào cũng có thể được chuyển làm consttham chiếu.
Hai khái niệm này hoàn toàn khác nhau về bản chất, và chỉ xảy ra khi sử dụng cùng một tên (và cả hai đều khác với JavaScript const).