Rilevare quando un oggetto const viene passato a una funzione che lo modifica, in Dart
Prendi questo esempio:
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);
}
L'esecuzione del codice precedente risulta in un runtime Uncaught Error
, ma la rimozione del file const
da
var foo = const Foo([1,2,3,4]);
gli permette di funzionare.
Questo mi sembra un bug perché la variabile const può essere mutata e dart lo rileva in fase di esecuzione, il che significa che ha i mezzi per rilevare quando un oggetto const viene modificato, ma non avrebbe dovuto essere rilevato in fase di compilazione, visto come le variabili const sono chiamate " costanti in fase di compilazione ".
Se questo non è un bug, c'è qualcosa in dart che ci permette di rilevare in fase di compilazione quando una const
variabile potrebbe essere mutata da un'operazione?
In C ++, il compilatore genera errori quando proviamo a fare qualcosa di simile. C'è qualcosa che possiamo fare in Dart per evitare di riscontrare questo errore in fase di esecuzione?
Risposte
No. Dart const
è una funzionalità in fase di compilazione relativa alla creazione di oggetti, ma non si riflette nel sistema di tipi. Non puoi dire dal tipo di qualsiasi oggetto se è una costante o meno.
Di solito questo non è un problema perché un'istanza di una classe che può essere const non è modificabile. Non è garantito che sia profondamente immutabile, ma non è possibile modificare i campi dell'istanza stessa.
Liste, insiemi e mappe possono essere sia costanti che mutevoli. Questo è quello che vedi qui. L'argomento della lista a const Foo(const [1, 2, 3, 4])
è costante, anche se rimuovi il ridondante const
dal letterale della lista. Avresti lo stesso problema con new Foo(const [1, 2, 3, 4])
, che fornirebbe anche un immutabile foo.bar
, ma da cui altrimenti sarebbe indistinguibile new Foo([1, 2, 3, 4])
. L'unica vera differenza è se l'elenco è modificabile o meno, e l'unico modo per rilevarlo è provare a modificarlo.
Liste, set e mappe non forniscono alcun modo per rilevare se sono modificabili o meno, tranne provare e rilevare l'errore.
Quando si confronta con C ++, la nozione di essere di Dart const
è una proprietà dell'oggetto o, in realtà, il modo in cui l'oggetto viene creato. Ciò potrebbe avere alcune conseguenze per l'oggetto. A const Foo(..)
crea semplicemente un Foo
oggetto normale , ma può solo creare oggetti profondamente immutabili e sono canonizzati. A const [...]
o const {...}
crea un diverso tipo di elenco / mappa / insieme rispetto al valore letterale non const, ma non è visibile nel tipo.
In C ++, being const
è una proprietà di un riferimento a un oggetto e limita il modo in cui tale riferimento può essere utilizzato, ma non ci sono oggetti costanti in quanto tali. Qualsiasi oggetto può essere passato come const
riferimento.
I due concetti sono di natura completamente diversa e per caso usano lo stesso nome (e sono anche entrambi diversi da JavaScript const
).