Para manipular datos necesitas hacer tres cosas fundamentales: transformarlos (aritmética), compararlos (booleanos) o guardarlos (asignación).
Cuando usas operadores aritméticos como + o *, estás transformando valores. Un detalle vital en Dart es la división: el operador / siempre devuelve un double, incluso si el resultado es un número entero (por ejemplo, 10 / 2 es 5.0). Si lo que necesitas es el resultado entero descartando los decimales, debes usar ~/. Para obtener el residuo de una división, utilizas el operador de módulo %.
Para la lógica de control, usas los operadores de comparación como < o >. Un punto crítico para entender es el operador ==: en Dart, por defecto, cuando comparas objetos complejos (como listas o clases propias), el operador comprueba la identidad (si son exactamente el mismo objeto en la memoria) y no la igualdad de sus contenidos. Sin embargo, para tipos primitivos como int o double, compara el valor.
Para la asignación, no solo usas =. Tienes los operadores compuestos como += para sumar y asignar a la vez, o *= para multiplicar. Además, si trabajas con tipos que aceptan nulos, el operador ??= (asignación condicional nula) es esencial: asigna un valor a una variable solo si esta es actualmente null.
Si mezclas estos operadores sin usar paréntesis (), Dart aplicará la precedencia de operadores (el orden matemático estándar, donde la multiplicación tiene prioridad sobre la suma). Si no tienes cuidado con el orden, tu lógica matemática será errónea aunque el código compile perfectamente.
void main() {
double precioBase = 19.99;
int cantidad = 5;
double impuesto = 0.15;
double? descuentoAplicado; // Variable que puede ser null
// 1. Aritmética y Precedencia
// La multiplicación tiene prioridad, pero usamos paréntesis para mayor claridad
double subtotal = precioBase * cantidad;
double impuestoTotal = subtotal * impuesto;
double totalConImpuestos = subtotal + impuestoTotal;
// 2. División entera y residuo (módulo)
// Queremos saber cuántas cajas llenas tenemos y cuántos items sobran
int itemsPorCaja = 4;
int cajasLlenas = cantidad ~/ itemsPorCaja; // Resultado: 1
int itemsSueltos = cantidad % itemsPorCaja; // Resultado: 1
// 3. Asignación compuesta
double saldoTienda = 500.0;
saldoTienda -= totalConImpuestos; // Resta el total al saldo inicial
// 4. Asignación condicional nula (Null-aware assignment)
// Solo asignamos el valor si 'descuentoAplicado' es null
descuentoAplicado ??= 5.0;
descuentoAplicado ??= 10.0; // No hace nada, porque ya tiene 5.0
// 5. Comparación
bool esPedidoGrande = cantidad > 10;
bool esPrecioRedondeado = totalConImpuestos.toInt() == 32;
print('--- Resumen de Pedido ---');
print('Subtotal: \$${subtotal.toStringAsFixed(2)}');
print('Total con impuestos: \$${totalConImpuestos.toStringAsFixed(2)}');
print('Cajas completas: $cajasLlenas (sobran $itemsSueltos items)');
print('Saldo en caja: \$${saldoTienda.toStringAsFixed(2)}');
print('Descuento aplicado: \$$descuentoAplicado');
print('¿Es pedido grande?: $esPedidoGrande');
print('¿El total redondeado es 32?: $esPrecioRedondeado');
}
Análisis del código
En el cálculo de totalConImpuestos, Dart sigue la jerarquía de operaciones: primero realiza precioBase * cantidad y luego suma impuestoTotal. Aunque en este caso la precedencia natural de la multiplicación ayuda, usar paréntesis en expresiones complejas es una buena práctica para evitar errores de lógica.
Al trabajar con cantidad (que es 5) y itemsPorCaja (que es 4), el operador ~/ nos devuelve 1, ya que realiza una división entera ignorando el decimal. El operador % nos devuelve 1, que es el resto que queda tras repartir los items en las cajas.
Con descuentoAplicado, aplicamos el operador ??=. En la primera llamada, como la variable era null, se le asignó 5.0. En la segunda llamada, como ya contenía un valor, el operador no hizo nada, preservando el valor original. Esto es extremadamente útil para establecer valores por defecto en configuraciones o estados iniciales.
Finalmente, observa la comparación totalConImpuestos.toInt() == 32. Aquí estamos comparando un entero con otro entero. Si intentáramos comparar totalConImpuestos == 32 directamente, el resultado sería false porque totalConImpuestos es un double (probablemente 32.48...) y la igualdad entre tipos diferentes o valores decimales exactos puede ser engañosa.
El error frecuente
Un error común cuando vienes de otros lenguajes es asumir que la división / siempre te dará un número entero si la división es exacta. En Dart, 10 / 2 resulta en 5.0 (un double). Si intentas asignar ese resultado a una variable de tipo int, el compilador de Dart te dará un error de tipos.
// ❌ ERROR: No puedes asignar un double a un int int resultado = 10 / 2; // ✅ CORRECTO: Usa el operador de división entera int resultado = 10 ~/ 2; // ✅ CORRECTO: O acepta que es un double double resultado = 10 / 2;
N° 16