El lenguaje Dart está diseñado para que sea fácil de aprender para programadores que provienen de otros lenguajes, pero tiene algunas características únicas. Este codelab te guiará a través de las características más importantes de estos lenguajes.
Los editores integrados en este codelab tienen fragmentos de código parcialmente completados. Puedes utilizar estos editores para probar tus conocimientos completando el código y haciendo clic en el botón Run. Los editores también contienen código de test exhaustivo; no edites el código de test, pero siéntete libre de estudiarlo para aprender sobre los tests.
Si necesitas ayuda, expande el menú desplegable Solución para… debajo de cada DartPad para obtener una explicación y la respuesta.
Interpolación de cadenas
Para poner el valor de una expresión dentro de una cadena, usa ${expression}. Si la expresión es un identificador, puedes omitir {}.
Aquí hay algunos ejemplos del uso de la interpolación de cadenas:
String
Resultado
'${3 + 2}'
'5'
'${"word".toUpperCase()}'
'WORD'
'$myObject'
El valor de myObject.toString()
Ejemplo de código
La siguiente función toma dos números enteros como parámetros. Haz que devuelva una cadena que contenga ambos números enteros separados por un espacio. Por ejemplo, stringify(2, 3) debería devolver '2 3'.
Variables que aceptan null
Dart aplica un comportamiento null-safety sólido. Esto significa que los valores no pueden ser nulos a menos que le digas que pueden serlo. En otras palabras, los tipos por defecto no aceptan valores null.
Por ejemplo, considera el siguiente código. Con null-safety, este código devuelve un error. Una variable de tipo int no puede tener el valor null:
Al crear una variable, agrega ? al tipo para indicar que la variable puede ser null:
Puedes simplificar un poco ese código porque, en todas las versiones de Dart, null es el valor predeterminado para las variables no inicializadas:
Para obtener más información sobre null-safety en Dart, lee la guía de null-safety ↗.
Ejemplo de código
Intenta declarar dos variables a continuación:
Una de String nullable (que acepta valores null) llamada name con el valor 'Jane'.
Una de String nullable llamada address con el valor null.
Ignora todos los errores iniciales en DartPad.
Operadores con reconocimiento de nulos
Dart ofrece algunos operadores útiles para tratar con valores que pueden ser nulos. Uno es el operador de asignación ??=, que asigna un valor a una variable sólo si esa variable es actualmente null:
Otro operador que reconoce nulos es ??, que devuelve la expresión de su izquierda a menos que el valor de esa expresión sea nulo, en cuyo caso evalúa y devuelve la expresión de su derecha:
Ejemplo de código
Intenta sustituir los operadores ??= y ?? para implementar el comportamiento descrito en el siguiente fragmento.
Ignora todos los errores iniciales en DartPad.
Acceso condicional a una propiedad
Para proteger el acceso a una propiedad o método de un objeto que podría ser nulo, coloca un signo de interrogación (?) antes del punto (.):
El código anterior es equivalente al siguiente:
Puedes encadenar múltiples usos de ?. juntos en una sola expresión:
El código anterior devuelve null (y nunca llama a someMethod()) si myObject o myObject.someProperty es null.
Ejemplo de código
La siguiente función toma una cadena que acepta valores null como parámetro. Intenta utilizar el acceso condicional a la propiedad para que devuelva la versión mayúscula de str, o null si str es null.
Literales de colecciones
Dart tiene soporte integrado para lists, maps y sets. Puedes crearlos usando literales:
La inferencia de tipos de Dart puede asignar tipos a estas variables por ti. En este caso, los tipos inferidos son List<String>, Set<String> y Map<String, int>.
O puedes especificar el tipo tú mismo:
Especificar tipos es útil cuando inicializas una lista con contenidos de un subtipo, pero aún quieres que la lista sea List<BaseType>:
Ejemplo de código
Intenta asignar a las siguientes variables los valores indicados. Reemplaza los valores nulos existentes.
Sintaxis de flecha
Es posible que hayas visto el símbolo => en el código Dart. Esta sintaxis de flecha es una forma de definir una función que ejecuta la expresión a su derecha y devuelve su valor.
Por ejemplo, considera esta llamada al método any() de la clase List:
Aquí tienes una forma más sencilla de escribir ese código:
Ejemplo de código
Intenta terminar las siguientes declaraciones, que usan sintaxis de flecha.
Cascadas
Para realizar una secuencia de operaciones sobre un mismo objeto, usa cascadas (..). Todos hemos visto una expresión como esta:
Invoca someMethod() en myObject, y el resultado de la expresión es el valor de retorno de someMethod().
Aquí tienes la misma expresión con una cascada:
Aunque todavía invoca someMethod() en myObject, el resultado de la expresión no es el valor de retorno—¡es una referencia a myObject!
Usando cascadas, puedes encadenar operaciones que de otro modo requerirían declaraciones separadas. Por ejemplo, considera el siguiente código, que utiliza el operador de acceso condicional a miembros (?.) para leer las propiedades de button si no es null:
Para usar cascadas, puedes comenzar con la cascada null-shorting (?..), que garantiza que ninguna de las operaciones en cascada se intente en un objeto null. El uso de cascadas acorta el código y hace que la variable “button” sea innecesaria:
Ejemplo de código
Usa cascadas para crear una declaración única que establezca las propiedades anInt, aString y aList de un BigObject en 1, 'String!' y [3.0] (respectivamente) y luego llama a allDone().
Getters y setters
Puedes definir getters y setters siempre que necesites más control sobre una propiedad del que permite un simple campo.
Por ejemplo, puedes asegurarte de que el valor de una propiedad sea válido:
También puedes usar un getter para definir una propiedad calculada:
Ejemplo de código
Imagina que tienes una clase de carrito de compras que mantiene una List<doble> privada de precios. Agrega lo siguiente:
Un getter llamado total que devuelve la suma de los precios.
Un setter que reemplaza la lista por una nueva, siempre y cuando la nueva lista no contenga ningún precio negativo (en cuyo caso el setter debería generar una InvalidPriceException).
Ignora todos los errores iniciales en DartPad.
Parámetros posicionales opcionales
Dart tiene dos tipos de parámetros de función: posicionales y con nombre. Los parámetros posicionales son del tipo con el que probablemente estés familiarizado:
Con Dart, puedes hacer que estos parámetros posicionales sean opcionales envolviéndolos entre paréntesis:
Los parámetros posicionales opcionales siempre son los últimos en la lista de parámetros de una función. Su valor predeterminado es null a menos que proporciones otro valor predeterminado:
Ejemplo de código
Implementa una función llamada joinWithCommas() que acepte de uno a cinco números enteros y luego devuelve una cadena de esos números separados por comas. A continuación se muestran algunos ejemplos de llamadas a funciones y valores devueltos:
Usando una sintaxis de llave al final de la lista de parámetros, puedes definir parámetros que tienen nombres.
Los parámetros con nombre son opcionales a menos que estén marcados explícitamente como required.
Como es de esperar, el valor predeterminado de un parámetro con nombre que acepta valores null es null, pero puedes proporcionar un valor predeterminado personalizado.
Si el tipo de un parámetro no admite valores null, entonces debes proporcionar un valor predeterminado (como se muestra en el siguiente código) o marcar el parámetro como required (como se muestra en la sección sobre el constructor).
Una función no puede tener parámetros posicionales y con nombre opcionales.
Ejemplo de código
Agrega un método de instancia copyWith() a la clase MyDataObject. Debería tomar tres parámetros con nombre que acepten valores null:
int? newInt
String? newString
double? newDouble
Tu método copyWith() deberá devolver un nuevo MyDataObject basado en la instancia actual, con datos de los parámetros anteriores (si los hay) copiados en las propiedades del objeto. Por ejemplo, si newInt no es null, copia su valor en anInt.
Ignora todos los errores iniciales en DartPad.
Excepciones
El código Dart puede generar y detectar excepciones. A diferencia de Java, todas las excepciones de Dart son excepciones no comprobadas. Los métodos no declaran qué excepciones podrían generar y no es necesario detectar ninguna excepción.
Dart proporciona los tipos Excepción y Error, pero puedes lanzar cualquier objeto que no sea null:
Usa las palabras clave try, on y catch cuando manejes excepciones:
La palabra clave try funciona como en la mayoría de los demás lenguajes. Utiliza la palabra clave on para filtrar excepciones específicas por tipo y la palabra clave catch para obtener una referencia al objeto de excepción.
Si no puedes manejar completamente la excepción, usa la palabra clave rethrow para propagar la excepción:
Para ejecutar código independientemente de que se produzca una excepción o no, usa finally:
Ejemplo de código
Implementa tryFunction() a continuación. Debería ejecutar un método no confiable y luego hacer lo siguiente:
Si untrustworthy() arroja una ExceptionWithMessage, llama a logger.logException con el tipo de excepción y el mensaje (intenta usar on y catch).
Si untrustworthy() arroja una Excepción, llama a logger.logException con el tipo de excepción (intenta usar on para esto).
Si untrustworthy() arroja cualquier otro objeto, no detectes la excepción.
Después de que todo esté capturado y manejado, llama a logger.doneLogging (intenta usar finally).
Usando this en un constructor
Dart proporciona un atajo útil para asignar valores a propiedades en un constructor: usa this.propertyName al declarar el constructor:
Esta técnica también funciona para parámetros con nombre. Los nombres de las propiedades se convierten en los nombres de los parámetros:
En el código anterior, red, green y blue están marcados como required porque estos valores int no pueden ser null. Si agregas valores predeterminados, puedes omitir required:
Ejemplo de código
Agrega un constructor de una línea a MyClass que use la sintaxis this. para recibir y asignar valores para las tres propiedades de la clase.
Ignora todos los errores iniciales en DartPad.
Listas de inicializadores
A veces, cuando implementas un constructor, necesitas realizar alguna configuración antes de que se ejecute el cuerpo del constructor. Por ejemplo, los campos final deben tener valores antes de que se ejecute el cuerpo del constructor. Haz este trabajo en una lista de inicializadores, que va entre la firma del constructor y su cuerpo:
La lista de inicializadores también es un lugar útil para colocar aserciones, que se ejecutan solo durante el desarrollo:
Ejemplo de código
Completa el constructor FirstTwoLetters a continuación. Utiliza una lista de inicializadores para asignar los dos primeros caracteres de word a las propiedades letterOne y letterTwo. Para obtener crédito adicional, agregue un assert para captar palabras de menos de dos caracteres.
Ignora todos los errores iniciales en DartPad.
Constructores con nombre
Para permitir que las clases tengan múltiples constructores, Dart admite constructores con nombre:
Para usar un constructor con nombre, invócalo usando su nombre completo:
Ejemplo de código
Dale a la clase Color un constructor llamado Color.black que establezca las tres propiedades en cero.
Ignora todos los errores iniciales en DartPad.
Constructores factory
Dart admite constructores factory, que pueden devolver subtipos o incluso null. Para crear un constructor factory, utiliza la palabra clave factory:
Ejemplo de código
Completa el constructor factory llamado IntegerHolder.fromList, haciendo que haga lo siguiente:
Si la lista tiene un valor, crea un IntegerSingle con ese valor.
Si la lista tiene dos valores, crea un IntegerDouble con los valores en orden.
Si la lista tiene tres valores, crea un IntegerTriple con los valores en orden.
De lo contrario, arroja un Error.
Redireccionando constructores
A veces el único propósito de un constructor es redirigir a otro constructor en la misma clase. El cuerpo de un constructor de redireccionamiento está vacío y la llamada al constructor aparece después de dos puntos (:).
Ejemplo de código
¿Recuerdas la clase Color de arriba? Crea un constructor con nombre llamado black, pero en lugar de asignar manualmente las propiedades, rediríjelo al constructor predeterminado con ceros como argumentos.
Ignora todos los errores iniciales en DartPad.
Constructores constantes
Si tu clase produce objetos que nunca cambian, puedes hacer que estos objetos sean constantes en tiempo de compilación. Para hacer esto, define un constructor const y asegúrate de que todas las variables de instancia sean final.
Ejemplo de código
Modifica la clase Recipe para que sus instancias puedan ser constantes y crea un constructor constante que haga lo siguiente:
Tiene tres parámetros: ingredients, calories y milligramsOfSodium (en ese orden).
Utiliza la sintaxis this. para asignar automáticamente los valores de los parámetros a las propiedades del objeto del mismo nombre.
Es constante, con la palabra clave const justo antes de Recipe en la declaración del constructor.
Ignora todos los errores iniciales en DartPad.
¿Qué sigue?
Esperamos que hayas disfrutado usando este codelab para aprender o probar tu conocimiento de algunas de las características más interesantes del lenguaje Dart. Aquí hay algunas sugerencias sobre qué hacer ahora: