Menu
Coddy logo textTech

Campos Final y Const

Parte de la sección Programación Orientada a Objetos del Journey de Dart de Coddy — lección 18 de 110.

Al declarar campos en una clase, puedes usar final o const para controlar si los valores pueden cambiar después de la inicialización. Ambos crean valores inmutables, pero funcionan de manera diferente.

Un campo final solo se puede establecer una vez, pero su valor se determina en tiempo de ejecución. Puedes asignarlo en la declaración o a través de un constructor:

class Person {
  final String name;
  final DateTime createdAt = DateTime.now();
  
  Person(this.name);
}

Person p = Person('Alice');
// p.name = 'Bob';  // Error: no se puede reasignar un campo final

El name se establece cuando se crea el objeto, y createdAt captura la hora actual. Ambos valores se bloquean después de la inicialización.

Un campo static const debe tener un valor conocido en tiempo de compilación. Pertenece a la clase misma y se comparte entre todas las instancias:

class Circle {
  static const double pi = 3.14159;
  final double radius;
  
  Circle(this.radius);
  
  double get area => Circle.pi * radius * radius;
}

La diferencia clave: los campos final pueden contener valores calculados en tiempo de ejecución (como DateTime.now()), mientras que const requiere constantes en tiempo de compilación. Los campos de instancia no pueden ser const directamente; solo se permite static const a nivel de clase.

challenge icon

Desafío

Fácil

Vamos a construir un sistema de catálogo de productos que demuestre la diferencia entre los campos final y static const. Crearás productos con propiedades inmutables y valores de configuración compartidos.

Organizarás tu código en dos archivos:

  • product.dart: Define una clase Product que represente un artículo en una tienda. Tu clase debe tener:
    • Un static const double taxRate establecido en 0.08 (tasa de impuesto del 8% compartida por todos los productos)
    • Un static const String currency establecido en 'USD'
    • Un final String name para el nombre del producto (establecido a través del constructor)
    • Un final double basePrice para el precio base del producto (establecido a través del constructor)
    • Un final String sku (unidad de mantenimiento de existencias) que combine un prefijo con el nombre del producto, calculado en una lista de inicialización como 'SKU-' seguido del nombre en mayúsculas
    • Un constructor que reciba name y basePrice
    • Un getter priceWithTax que calcule el precio incluyendo el impuesto
    • Un método display() que imprima la información del producto
  • main.dart: Importa tu clase de producto y crea dos productos:
    • Un 'Laptop' con precio base 999.99
    • Un 'Mouse' con precio base 29.99
    Llama a display() en cada producto en el orden indicado anteriormente.

El método display() debe imprimir exactamente en este formato:

[sku] - [name]: [basePrice] [currency] (with tax: [priceWithTax] [currency])

Redondea priceWithTax a 2 decimales usando toStringAsFixed(2) al mostrarlo.

Salida esperada:

SKU-LAPTOP - Laptop: 999.99 USD (with tax: 1079.99 USD)
SKU-MOUSE - Mouse: 29.99 USD (with tax: 32.39 USD)

Hoja de referencia

Usa final para campos que se establecen una vez en tiempo de ejecución y no pueden cambiarse después. Usa static const para constantes en tiempo de compilación compartidas entre todas las instancias de una clase.

Los campos final se establecen en tiempo de ejecución y pueden inicializarse en la declaración o en el constructor:

class Person {
  final String name;
  final DateTime createdAt = DateTime.now();
  
  Person(this.name);
}

Los campos static const deben tener valores constantes en tiempo de compilación y pertenecen a la propia clase:

class Circle {
  static const double pi = 3.14159;
  final double radius;
  
  Circle(this.radius);
  
  double get area => Circle.pi * radius * radius;
}

Puedes calcular los valores de los campos final en una lista de inicializadores:

class Product {
  final String name;
  final String sku;
  
  Product(this.name) : sku = 'SKU-${name.toUpperCase()}';
}

Diferencias clave:

  • final: Valores en tiempo de ejecución, pueden ser diferentes para cada instancia
  • static const: Constantes en tiempo de compilación, compartidas entre todas las instancias
  • Los campos de instancia no pueden ser const directamente; solo se permite static const

Pruébalo tú mismo

import 'product.dart';

void main() {
  // TODO: Crea un Product llamado 'Laptop' con un precio base de 999.99
  
  // TODO: Crea un Product llamado 'Mouse' con un precio base de 29.99
  
  // TODO: Llama a display() en cada producto en orden (Laptop primero, luego Mouse)
  
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos