Creo que la respuesta de Lasse en el blog de Chris Storms es una gran explicación.
Espero que no les importe que copie el contenido.
Esta es una buena explicación de los campos finales, pero realmente no explica los constructores const. Nada en estos ejemplos usa realmente que los constructores sean constructores constantes. Cualquier clase puede tener campos finales, constructores constantes o no.
Un campo en Dart es realmente una ubicación de almacenamiento anónima combinada con un captador y configurador creado automáticamente que lee y actualiza el almacenamiento, y también se puede inicializar en una lista de inicializadores del constructor.
Un campo final es el mismo, solo que sin el setter, por lo que la única forma de establecer su valor es en la lista de inicializadores del constructor, y no hay forma de cambiar el valor después de eso - de ahí el "final".
El objetivo de los constructores const no es inicializar los campos finales, cualquier constructor generativo puede hacer eso. El punto es crear valores constantes en tiempo de compilación: objetos donde todos los valores de campo ya se conocen en el tiempo de compilación, sin ejecutar ninguna declaración.
Eso impone algunas restricciones a la clase y al constructor. Un constructor const no puede tener un cuerpo (¡no se ejecutan sentencias!) Y su clase no debe tener ningún campo no final (el valor que "conocemos" en el momento de la compilación no debe poder cambiar más adelante). La lista de inicializadores también debe inicializar campos a otras constantes en tiempo de compilación, por lo que los lados derechos están limitados a "expresiones constantes en tiempo de compilación" [1]. Y debe tener el prefijo "const"; de lo contrario, obtendrá un constructor normal que satisfaga esos requisitos. Eso está perfectamente bien, simplemente no es un constructor constante.
Para usar un constructor const para crear realmente un objeto constante en tiempo de compilación, luego reemplaza "nuevo" por "const" en una expresión "nueva". Aún puede usar "new" con un constructor const, y aún creará un objeto, pero será un nuevo objeto normal, no un valor constante en tiempo de compilación. Es decir: un constructor const también se puede usar como un constructor normal para crear objetos en tiempo de ejecución, así como para crear objetos constantes en tiempo de compilación en tiempo de compilación.
Entonces, como ejemplo:
class Point {
static final Point ORIGIN = const Point(0, 0);
final int x;
final int y;
const Point(this.x, this.y);
Point.clone(Point other): x = other.x, y = other.y; //[2]
}
main() {
// Assign compile-time constant to p0.
Point p0 = Point.ORIGIN;
// Create new point using const constructor.
Point p1 = new Point(0, 0);
// Create new point using non-const constructor.
Point p2 = new Point.clone(p0);
// Assign (the same) compile-time constant to p3.
Point p3 = const Point(0, 0);
print(identical(p0, p1)); // false
print(identical(p0, p2)); // false
print(identical(p0, p3)); // true!
}
Las constantes de tiempo de compilación se canonicalizan. Eso significa que no importa cuántas veces escriba "const Point (0,0)", solo crea un objeto. Eso puede ser útil, pero no tanto como parece, ya que puede crear una variable constante para mantener el valor y usar la variable en su lugar.
Entonces, ¿para qué sirven las constantes en tiempo de compilación?
- Son útiles para enumeraciones.
- Puede utilizar valores constantes en tiempo de compilación en casos de cambio.
- Se utilizan como anotaciones.
Las constantes de tiempo de compilación solían ser más importantes antes de que Dart cambiara a la inicialización lenta de variables. Antes de eso, solo podía declarar una variable global inicializada como "var x = foo;" si "foo" fuera una constante en tiempo de compilación. Sin ese requisito, la mayoría de los programas se pueden escribir sin utilizar ningún objeto constante.
Entonces, breve resumen: los constructores Const son solo para crear valores constantes en tiempo de compilación.
/ L
[1] O realmente: "Expresiones constantes potencialmente en tiempo de compilación" porque también puede referirse a los parámetros del constructor. [2] Entonces, sí, una clase puede tener constructores const y no const al mismo tiempo.