Saltar al contenido principal

Operadores

Aprende sobre los operadores compatibles con Dart.

Dart admite los operadores que se muestran en la siguiente tabla. La tabla muestra la asociatividad de los operadores de Dart y su precedencia de operadores de mayor a menor, las cuales son una aproximación de las relaciones de los operadores en Dart. Puedes implementar muchos de estos operadores como miembros de clase.

DescripciónOperadorAsociatividad
sufijo unario (unary postfix) expr ++    expr --    ()    []    ?[]    .    ?.    ! Ninguna
prefijo unario (unary prefix) - expr    ! expr    ~ expr    ++ expr    -- expr       await expr Ninguna
multiplicativo *    /    %  ~/ Izquierda
aditivo+    -Izquierda
desplazamiento (shift) <<    >>    >>> Izquierda
AND a nivel de bits&Izquierda
XOR a nivel de bits^Izquierda
OR a nivel de bits|Izquierda
relacional y de prueba de tipo >=    >    <=    <    as    is    is! Ninguna
igualdad==    !=Ninguna
AND lógico&&Izquierda
OR lógico||Izquierda
if-null??Izquierda
condicional expr1    ?    expr2    :    expr3 Derecha
cascada (cascade)..    ?..Izquierda
asignación =    *=    /=    +=    -=    &=    ^=    etc. Derecha
propagación (spread) (Ver nota) ...    ...? Ninguna

Cuando usas operadores, creas expresiones. Aquí tienes algunos ejemplos de expresiones con operadores:

dart
a++
a + b
a = b
a == b
c ? a : b
a is T

Ejemplo de precedencia de operadores

#

En la tabla de operadores, cada operador tiene una precedencia mayor que los operadores de las filas siguientes. Por ejemplo, el operador multiplicativo % tiene una precedencia mayor que (y por lo tanto se ejecuta antes que) el operador de igualdad ==, el cual tiene una precedencia mayor que el operador lógico AND &&. Esa precedencia significa que las siguientes dos líneas de código se ejecutan de la misma manera:

dart
// Parentheses improve readability.
if ((n % i == 0) && (d % i == 0)) {
  // ...
}

// Harder to read, but equivalent.
if (n % i == 0 && d % i == 0) {
  // ...
}

Operadores aritméticos

#

Dart admite los operadores aritméticos habituales, como se muestra en la siguiente tabla.

OperadorSignificado
+Sumar
-Restar
-expr Menos unario, también conocido como negación (invierte el signo de la expresión)
*Multiplicar
/Dividir
~/Dividir, devolviendo un resultado entero
%Obtener el resto de una división entera (módulo)

Ejemplo:

dart
assert(2 + 3 == 5);
assert(2 - 3 == -1);
assert(2 * 3 == 6);
assert(5 / 2 == 2.5); // Result is a double
assert(5 ~/ 2 == 2); // Result is an int
assert(5 % 2 == 1); // Remainder

assert('5/2 = ${5 ~/ 2} r ${5 % 2}' == '5/2 = 2 r 1');

Dart también admite operadores de incremento y decremento tanto de prefijo como de sufijo.

OperadorSignificado
++var var   =   var + 1 (el valor de la expresión es var + 1 )
var++ var   =   var + 1 (el valor de la expresión es var )
--var var   =   var - 1 (el valor de la expresión es var - 1 )
var-- var   =   var - 1 (el valor de la expresión es var )

Ejemplo:

dart
int a;
int b;

a = 0;
b = ++a; // Increment a before b gets its value.
assert(a == b); // 1 == 1

a = 0;
b = a++; // Increment a after b gets its value.
assert(a != b); // 1 != 0

a = 0;
b = --a; // Decrement a before b gets its value.
assert(a == b); // -1 == -1

a = 0;
b = a--; // Decrement a after b gets its value.
assert(a != b); // -1 != 0

Operadores de igualdad y relacionales

#

La siguiente tabla enumera los significados de los operadores de igualdad y relacionales.

OperadorSignificado
==Igual; consulta la discusión más abajo
!=No igual
>Mayor que
<Menor que
>=Mayor o igual que
<=Menor o igual que

Para comprobar si dos objetos x e y representan lo mismo, usa el operador ==. (En el caso poco común de que necesites saber si dos objetos son exactamente el mismo objeto, usa la función identical() en su lugar). Así es como funciona el operador ==:

  1. Si x o y es nulo, devuelve true si ambos son nulos, y false si solo uno es nulo.

  2. Devuelve el resultado de invocar el método == en x con el argumento y. (Así es, los operadores como == son métodos que se invocan en su primer operando. Para más detalles, consulta Operadores).

Aquí tienes un ejemplo del uso de cada uno de los operadores de igualdad y relacionales:

dart
assert(2 == 2);
assert(2 != 3);
assert(3 > 2);
assert(2 < 3);
assert(3 >= 3);
assert(2 <= 3);

Operadores de prueba de tipos

#

Los operadores as, is e is! son muy prácticos para comprobar tipos en tiempo de ejecución.

OperadorSignificado
as Conversión de tipo (Typecast) (también usado para especificar prefijos de biblioteca )
isVerdadero si el objeto tiene el tipo especificado
is!Verdadero si el objeto no tiene el tipo especificado

El resultado de obj is T es true si obj implementa la interfaz especificada por T. Por ejemplo, obj is Object? siempre es true.

Usa el operador as para convertir un objeto a un tipo particular si y solo si estás seguro de que el objeto es de ese tipo. Ejemplo:

dart
(employee as Person).firstName = 'Bob';

Si no estás seguro de que el objeto sea de tipo T, usa is T para comprobar el tipo antes de usar el objeto.

dart
if (employee is Person) {
  // Type check
  employee.firstName = 'Bob';
}

Operadores de asignación

#

Como ya has visto, puedes asignar valores usando el operador =. Para asignar solo si la variable asignada es nula, usa el operador ??=.

dart
// Assign value to a
a = value;
// Assign value to b if b is null; otherwise, b stays the same
b ??= value;

Los operadores de asignación compuesta como += combinan una operación con una asignación.

= *= %= >>>= ^=
+= /= <<= &= |=
-=~/=>>=

Así es como funcionan los operadores de asignación compuesta:

Asignación compuestaExpresión equivalente
For an operator op: a op= b a = a op b
Example:a += ba = a + b

El siguiente ejemplo utiliza operadores de asignación y de asignación compuesta:

dart
var a = 2; // Assign using =
a *= 3; // Assign and multiply: a = a * 3
assert(a == 6);

Operadores lógicos

#

Puedes invertir o combinar expresiones booleanas usando los operadores lógicos.

OperadorSignificado
!expr invierte la siguiente expresión (cambia false a true, y viceversa)
||OR lógico
&&AND lógico

Aquí tienes un ejemplo del uso de los operadores lógicos:

dart
if (!done && (col == 0 || col == 3)) {
  // ...Do something...
}

Operadores de desplazamiento y a nivel de bits

#

Puedes manipular los bits individuales de los números en Dart. Normalmente, usarías estos operadores de desplazamiento y a nivel de bits con enteros.

OperadorSignificado
&AND
|OR
^XOR
~expr Complemento unario a nivel de bits (los 0 se convierten en 1; los 1 se convierten en 0)
<<Desplazar a la izquierda
>>Desplazar a la derecha
>>>Desplazar a la derecha sin signo

Aquí tienes un ejemplo del uso de los operadores de desplazamiento y a nivel de bits:

dart
final value = 0x22;
final bitmask = 0x0f;

assert((value & bitmask) == 0x02); // AND
assert((value & ~bitmask) == 0x20); // AND NOT
assert((value | bitmask) == 0x2f); // OR
assert((value ^ bitmask) == 0x2d); // XOR

assert((value << 4) == 0x220); // Shift left
assert((value >> 4) == 0x02); // Shift right

// Shift right example that results in different behavior on web
// because the operand value changes when masked to 32 bits:
assert((-value >> 4) == -0x03);

assert((value >>> 4) == 0x02); // Unsigned shift right
assert((-value >>> 4) > 0); // Unsigned shift right

Expresiones condicionales

#

Dart tiene dos operadores que te permiten evaluar expresiones de forma concisa que de otro modo podrían requerir sentencias if-else:

condition ? expr1 : expr2

Si condition es true, evalúa expr1 (y devuelve su valor); de lo contrario, evalúa y devuelve el valor de expr2.

expr1 ?? expr2

Si expr1 no es nulo, devuelve su valor; de lo contrario, evalúa y devuelve el valor de expr2.

Cuando necesites asignar un valor basado en una expresión booleana, considera usar el operador condicional ? y :.

dart
var visibility = isPublic ? 'public' : 'private';

Si la expresión booleana comprueba si hay un valor nulo, considera usar el operador if-null ?? (también conocido como operador de fusión de nulos o null-coalescing).

dart
String playerName(String? name) => name ?? 'Guest';

El ejemplo anterior se podría haber escrito de al menos otras dos formas, pero no de manera tan sucinta:

dart
// Slightly longer version uses ?: operator.
String playerName(String? name) => name != null ? name : 'Guest';

// Very long version uses if-else statement.
String playerName(String? name) {
  if (name != null) {
    return name;
  } else {
    return 'Guest';
  }
}

Notación de cascada

#

Las cascadas (.., ?..) te permiten realizar una secuencia de operaciones en el mismo objeto. Además de acceder a miembros de instancia, también puedes llamar a métodos de instancia en ese mismo objeto. Esto a menudo te ahorra el paso de crear una variable temporal y te permite escribir código más fluido.

Considera el siguiente código:

dart
var paint = Paint()
  ..color = Colors.black
  ..strokeCap = StrokeCap.round
  ..strokeWidth = 5.0;

El constructor, Paint(), devuelve un objeto Paint. El código que sigue a la notación de cascada opera sobre este objeto, ignorando cualquier valor que pueda ser devuelto.

El ejemplo anterior es equivalente a este código:

dart
var paint = Paint();
paint.color = Colors.black;
paint.strokeCap = StrokeCap.round;
paint.strokeWidth = 5.0;

Si el objeto sobre el cual opera la cascada puede ser nulo, entonces usa una cascada con cortocircuito de nulos (null-shorting) (?..) para la primera operación. Comenzar con ?.. garantiza que no se intente realizar ninguna de las operaciones de cascada en ese objeto nulo.

dart
document.querySelector('#confirm') // Get an object.
  ?..textContent =
      'Confirm' // Use its members.
  ..classList.add('important')
  ..onClick.listen((e) => window.alert('Confirmed!'))
  ..scrollIntoView();

El código anterior es equivalente al siguiente:

dart
final button = document.querySelector('#confirm');
button?.textContent = 'Confirm';
button?.classList.add('important');
button?.onClick.listen((e) => window.alert('Confirmed!'));
button?.scrollIntoView();

También puedes anidar cascadas. Por ejemplo:

dart
final addressBook =
    (AddressBookBuilder()
          ..name = 'jenny'
          ..email = 'jenny@example.com'
          ..phone =
              (PhoneNumberBuilder()
                    ..number = '415-555-0100'
                    ..label = 'home')
                  .build())
        .build();

Ten cuidado de construir tu cascada sobre una función que devuelva un objeto real. Por ejemplo, el siguiente código falla:

dart
var sb = StringBuffer();
sb.write('foo')
  ..write('bar'); // Error: method 'write' isn't defined for 'void'.

La llamada sb.write() devuelve void, y no puedes construir una cascada sobre void.

Operadores de propagación (spread)

#

Los operadores de propagación (spread) evalúan una expresión que produce una colección, desempaquetan los valores resultantes y los insertan en otra colección.

El operador de propagación no es en realidad una expresión de operador. La sintaxis .../...? es parte del propio literal de la colección. Por lo tanto, puedes obtener más información sobre los operadores de propagación en la página de Colecciones.

Debido a que no es un operador, la sintaxis no tiene ninguna "precedencia de operadores". De hecho, tiene la "precedencia" más baja: cualquier tipo de expresión es válida como objetivo de propagación, como por ejemplo:

dart
[...a + b]

Otros operadores

#

Has visto la mayoría de los operadores restantes en otros ejemplos:

OperadorNombreSignificado
()Aplicación de funciónRepresenta una llamada a una función
[] Acceso por subíndice Representa una llamada al operador anulable (overridable) []; ejemplo: fooList[1] pasa el entero 1 a fooList para acceder al elemento en el índice 1
?[] Acceso condicional por subíndice Como [] , pero el operando situado más a la izquierda puede ser nulo; ejemplo: fooList?[1] pasa el entero 1 a fooList para acceder al elemento en el índice 1 a menos que fooList sea nulo (en cuyo caso la expresión se evalúa como nula)
. Acceso a miembros Se refiere a una propiedad de una expresión; ejemplo: foo.bar selecciona la propiedad bar de la expresión foo
?. Acceso condicional a miembros Como . , pero el operando situado más a la izquierda puede ser nulo; ejemplo: foo?.bar selecciona la propiedad bar de la expresión foo a menos que foo sea nulo (en cuyo caso el valor de foo?.bar es nulo)
! Operador de aserción no nula (not-null assertion) Convierte una expresión a su tipo subyacente no anulable, lanzando una excepción en tiempo de ejecución si la conversión falla; ejemplo: foo!.bar asevera que foo no es nulo y selecciona la propiedad bar , a menos que foo sea nulo (en cuyo caso se lanza una excepción en tiempo de ejecución)

Para obtener más información sobre los operadores ., ?. y .., consulta Clases.