Обнаружение передачи константного объекта функции, которая его изменяет, в Dart
Вот пример:
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);
}
Выполнение приведенного выше кода приводит к запуску среды выполнения Uncaught Error
, но удаление const
из
var foo = const Foo([1,2,3,4]);
позволяет ему работать.
Мне это кажется ошибкой, потому что переменная const может быть изменена, и dart обнаруживает это во время выполнения, что означает, что у него есть средства для определения того, когда объект const изменяется, но не должно ли это быть обнаружено во время компиляции, поскольку Переменные const называются « константами времени компиляции ».
Если это не ошибка, есть ли в dart что-нибудь, что позволяет нам обнаруживать во время компиляции, когда const
переменная может быть изменена в результате операции?
В C ++ компилятор выдает ошибку, когда мы пытаемся сделать что-то подобное. Что мы можем сделать в Dart, чтобы избежать появления этой ошибки во время выполнения?
Ответы
Нет. Dart const
- это функция времени компиляции, связанная с созданием объекта, но она не отражается в системе типов. По типу объекта нельзя сказать, константа он или нет.
Обычно это не проблема, потому что экземпляр класса, который может быть константным, нельзя изменить. Не гарантируется, что он будет полностью неизменяемым, но для самого экземпляра нельзя изменить его поля.
Списки, наборы и карты могут быть как постоянными, так и изменяемыми. Вот что вы здесь видите. Аргумент списка const Foo(const [1, 2, 3, 4])
является постоянным, даже если вы удалите лишний в литерале const
списка. У вас будет такая же проблема с new Foo(const [1, 2, 3, 4])
, которая также предоставит неизменяемый foo.bar
, но в противном случае будет неотличима от new Foo([1, 2, 3, 4])
. Единственная реальная разница заключается в том, можно ли изменить список или нет, и единственный способ определить это - попытаться изменить его.
Списки, наборы и карты не предоставляют никакого способа определить, являются ли они изменяемыми или нет, кроме попытки и выявления ошибки.
По сравнению с C ++ понятие бытия Дарта const
является свойством объекта или, в действительности, способом создания объекта. Это может иметь некоторые последствия для объекта. A const Foo(..)
просто создает обычный Foo
объект, но может создавать только глубоко неизменяемые объекты, и они канонизированы. A const [...]
or const {...}
создает список / карту / набор другого типа, чем неконстантный литерал, но он не отображается в типе.
В C ++ бытие const
- это свойство ссылки на объект, которое ограничивает использование этой ссылки, но как таковые константные объекты отсутствуют. В качестве const
ссылки можно передать любой объект .
Эти две концепции полностью различаются по своей природе и просто используют одно и то же имя (и оба они отличаются от JavaScript const
).