Hoja de trucos de Dart
Aprende (o vuelve a aprender) de forma interactiva algunas de las características únicas de Dart.
El lenguaje Dart está diseñado para ser fácil de aprender para los desarrolladores que provienen de otros lenguajes, pero tiene algunas características únicas. Este tutorial te guiará a través de las más importantes de estas características del lenguaje.
Los editores integrados en este tutorial tienen fragmentos de código parcialmente completados. Puedes utilizar estos editores para poner a prueba tus conocimientos completando el código y haciendo clic en el botón Run. Los editores también contienen un código de prueba exhaustivo; no edites el código de prueba, pero siéntete libre de estudiarlo para aprender sobre pruebas.
Si necesitas ayuda, despliega el menú Solution for... debajo de cada DartPad para obtener una explicación y la respuesta.
Interpolación de strings
#Para colocar el valor de una expresión dentro de un string, usa ${expression}.
Si la expresión es un identificador, puedes omitir las {}.
Aquí tienes algunos ejemplos del uso de la interpolación de strings:
| String | Resultado |
|---|---|
'${3 + 2}' | '5' |
'${"word".toUpperCase()}' | 'WORD' |
'$myObject' | El valor de myObject.toString() |
Ejercicio
#La siguiente función toma dos enteros como parámetros.
Haz que devuelva un string que contenga ambos enteros separados por un espacio.
Por ejemplo, stringify(2, 3) debería devolver '2 3'.
Solución para el ejemplo de interpolación de strings
Tanto x como y son valores simples,
y la interpolación de strings de Dart se encargará de
convertirlos a representaciones de cadena.
Todo lo que necesitas hacer es usar el operador $ para
hacer referencia a ellos dentro de comillas simples, con un espacio en medio:
String stringify(int x, int y) {
return '$x $y';
}
Variables que admiten valores nulos
#Dart aplica sound null safety. Esto significa que los valores no pueden ser null a menos que indiques que pueden serlo. En otras palabras, los tipos por defecto no admiten valores nulos.
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:
int a = null; // INVALID.
Al crear una variable, añade ? al tipo para indicar
que la variable puede ser null:
int? a = null; // Valid.
Puedes simplificar un poco ese código porque, en todas las versiones de Dart,
null es el valor predeterminado para las variables no inicializadas:
int? a; // The initial value of a is null.
Para obtener más información sobre Null Safety en Dart, lee la guía de sound null safety.
Ejercicio
#Declara dos variables en este DartPad:
- Un
Stringque admite valores nulos llamadonamecon el valor'Jane'. - Un
Stringque admite valores nulos llamadoaddresscon el valornull.
Ignora todos los errores iniciales en el DartPad.
Solución para el ejemplo de variables que admiten valores nulos
Declara las dos variables como String seguido de ?.
Luego, asigna 'Jane' a name
y deja address sin inicializar:
String? name = 'Jane';
String? address;
Operadores null-aware
#Dart ofrece algunos operadores prácticos para manejar valores que podrían ser null. Uno es el
operador de asignación ??=, que asigna un valor a una variable solo si esa
variable es actualmente null:
int? a; // = null
a ??= 3;
print(a); // <-- Prints 3.
a ??= 5;
print(a); // <-- Still prints 3.
Otro operador null-aware es ??,
que devuelve la expresión a su izquierda a menos que
el valor de esa expresión sea null,
en cuyo caso evalúa y devuelve la expresión a su derecha:
print(1 ?? 3); // <-- Prints 1.
print(null ?? 12); // <-- Prints 12.
Ejercicio
#Intenta sustituir los operadores ??= y ??
para implementar el comportamiento descrito en el siguiente fragmento.
Ignora todos los errores iniciales en el DartPad.
Solución para el ejemplo de operadores null-aware
Todo lo que necesitas hacer en este ejercicio es
reemplazar los comentarios TODO con ?? o ??=.
Lee el texto anterior para asegurarte de que entiendes ambos,
y luego inténtalo:
// Substitute an operator that makes 'a string' be assigned to baz.
String? baz = foo ?? bar;
void updateSomeVars() {
// Substitute an operator that makes 'a string' be assigned to bar.
bar ??= 'a string';
}
Acceso condicional a propiedades
#Para proteger el acceso a una propiedad o método de un objeto que podría ser null,
coloca un signo de interrogación (?) antes del punto (.):
myObject?.someProperty
El código anterior es equivalente a lo siguiente:
(myObject != null) ? myObject.someProperty : null
Puedes encadenar múltiples usos de ?. juntos en una sola expresión:
myObject?.someProperty?.someMethod()
El código anterior devuelve null (y nunca llama a someMethod()) si
myObject o myObject.someProperty es null.
Ejercicio
#La siguiente función toma un string que admite valores nulos como parámetro.
Intenta usar el acceso condicional a propiedades para que
devuelva la versión en mayúsculas de str, o null si str
es null.
Solución para el ejemplo de acceso condicional a propiedades
Si este ejercicio quisiera que convirtieras un string a minúsculas de forma condicional,
podrías hacerlo así: str?.toLowerCase(). ¡Usa el método equivalente
para convertir un string a mayúsculas!
String? upperCaseIt(String? str) {
return str?.toUpperCase();
}
Literales de colección
#Dart tiene soporte incorporado para listas, mapas y conjuntos (sets). Puedes crearlos usando literales:
final aListOfStrings = ['one', 'two', 'three'];
final aSetOfStrings = {'one', 'two', 'three'};
final aMapOfStringsToInts = {'one': 1, 'two': 2, 'three': 3};
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:
final aListOfInts = <int>[];
final aSetOfInts = <int>{};
final aMapOfIntToDouble = <int, double>{};
Especificar los tipos es útil cuando inicializas una lista con contenidos de un subtipo,
pero aun así quieres que la lista sea List<BaseType>:
final aListOfBaseType = <BaseType>[SubType(), SubType()];
Ejercicio
#Intenta establecer las siguientes variables con los valores indicados. Reemplaza los valores nulos existentes.
Solución para el ejemplo de literales de colección
Añade un literal de lista, conjunto (set) o mapa después de cada signo igual (=).
Recuerda especificar los tipos para las declaraciones vacías,
ya que no se pueden inferir.
// Assign this a list containing 'a', 'b', and 'c' in that order:
final aListOfStrings = ['a', 'b', 'c'];
// Assign this a set containing 3, 4, and 5:
final aSetOfInts = {3, 4, 5};
// Assign this a map of String to int so that aMapOfStringsToInts['myKey'] returns 12:
final aMapOfStringsToInts = {'myKey': 12};
// Assign this an empty List<double>:
final anEmptyListOfDouble = <double>[];
// Assign this an empty Set<String>:
final anEmptySetOfString = <String>{};
// Assign this an empty Map of double to int:
final anEmptyMapOfDoublesToInts = <double, int>{};
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:
bool hasEmpty = aListOfStrings.any((s) {
return s.isEmpty;
});
Aquí tienes una forma más sencilla de escribir ese código:
bool hasEmpty = aListOfStrings.any((s) => s.isEmpty);
Ejercicio
#Intenta completar las siguientes sentencias, que utilizan la sintaxis de flecha.
Solución para el ejemplo de sintaxis de flecha
Para el producto, puedes usar * para multiplicar los tres valores entre sí.
Para incrementValue1, puedes usar el operador de incremento (++).
Para joinWithCommas, usa el método join que se encuentra en la clase List.
class MyClass {
int value1 = 2;
int value2 = 3;
int value3 = 5;
// Returns the product of the above values:
int get product => value1 * value2 * value3;
// Adds 1 to value1:
void incrementValue1() => value1++;
// Returns a string containing each item in the
// list, separated by commas (e.g. 'a,b,c'):
String joinWithCommas(List<String> strings) => strings.join(',');
}
Cascadas
#Para realizar una secuencia de operaciones en el mismo objeto, usa cascadas (..).
Todos hemos visto una expresión como esta:
myObject.someMethod()
Invoca someMethod() en myObject, y el resultado de
la expresión es el valor devuelto de someMethod().
Aquí tienes la misma expresión con una cascada:
myObject..someMethod()
Aunque sigue invocando a someMethod() en myObject, el resultado
de la expresión no es el valor devuelto, ¡sino una referencia a myObject!
Usando cascadas, puedes encadenar operaciones que
de otro modo requerirían sentencias 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:
final button = web.document.querySelector('#confirm');
button?.textContent = 'Confirm';
button?.classList.add('important');
button?.onClick.listen((e) => web.window.alert('Confirmed!'));
button?.scrollIntoView();
Para usar cascadas en su lugar,
puedes comenzar con la cascada null-shorting (?..),
que garantiza que no se intente ninguna de las operaciones en cascada
en un objeto null.
El uso de cascadas acorta el código
y hace innecesaria la variable button:
web.document.querySelector('#confirm')
?..textContent = 'Confirm'
..classList.add('important')
..onClick.listen((e) => web.window.alert('Confirmed!'))
..scrollIntoView();
Ejercicio
#Usa cascadas para crear una sola sentencia que
establezca las propiedades anInt, aString y aList de un
BigObject
en 1, 'String!' y [3.0] (respectivamente)
y luego llame a allDone().
Solución para el ejemplo de cascadas
La mejor solución para este ejercicio comienza con obj.. y
tiene cuatro operaciones de asignación encadenadas.
Comienza con return obj..anInt = 1,
luego añade otra cascada (..) y comienza la siguiente asignación.
BigObject fillBigObject(BigObject obj) {
return obj
..anInt = 1
..aString = 'String!'
..aList.add(3)
..allDone();
}
Getters y setters
#Puedes definir getters y setters siempre que necesites más control sobre una propiedad de lo que permite un campo simple.
Por ejemplo, puedes asegurarte de que el valor de una propiedad sea válido:
class MyClass {
int _aProperty = 0;
int get aProperty => _aProperty;
set aProperty(int value) {
if (value >= 0) {
_aProperty = value;
}
}
}
También puedes usar un getter para definir una propiedad calculada:
class MyClass {
final List<int> _values = [];
void addValue(int value) {
_values.add(value);
}
// A computed property.
int get count {
return _values.length;
}
}
Ejercicio
#Imagina que tienes una clase de carrito de compras que mantiene una
List<double> privada de precios.
Añade lo siguiente:
- Un getter llamado
totalque devuelva la suma de los precios - Un setter que reemplace la lista por una nueva,
siempre y cuando la nueva lista no contenga precios negativos
(en cuyo caso el setter debería lanzar una excepción
InvalidPriceException).
Ignora todos los errores iniciales en el DartPad.
Solución para el ejemplo de getters y setters
Dos funciones son muy útiles para este ejercicio.
Una es fold, que puede reducir una lista a un solo valor
(úsala para calcular el total).
La otra es any, que puede comprobar cada elemento de una lista
con una función que le proporciones
(úsala para comprobar si hay precios negativos en el setter de prices).
/// The total price of the shopping cart.
double get total => _prices.fold(0, (e, t) => e + t);
/// Set [prices] to the [value] list of item prices.
set prices(List<double> value) {
if (value.any((p) => p < 0)) {
throw InvalidPriceException();
}
_prices = value;
}
Parámetros posicionales opcionales
#Dart tiene dos tipos de parámetros de función: posicionales y nombrados. Los parámetros posicionales son del tipo con el que probablemente estés familiarizado:
int sumUp(int a, int b, int c) {
return a + b + c;
}
// ···
int total = sumUp(1, 2, 3);
Con Dart, puedes hacer que estos parámetros posicionales sean opcionales envolviéndolos en corchetes:
int sumUpToFive(int a, [int? b, int? c, int? d, int? e]) {
int sum = a;
if (b != null) sum += b;
if (c != null) sum += c;
if (d != null) sum += d;
if (e != null) sum += e;
return sum;
}
// ···
int total = sumUpToFive(1, 2);
int otherTotal = sumUpToFive(1, 2, 3, 4, 5);
Los parámetros posicionales opcionales siempre van al final de la lista de parámetros de una función. Su valor predeterminado es null a menos que proporciones otro valor predeterminado:
int sumUpToFive(int a, [int b = 2, int c = 3, int d = 4, int e = 5]) {
// ···
}
void main() {
int newTotal = sumUpToFive(1);
print(newTotal); // <-- prints 15
}
Ejercicio
#Implementa una función llamada joinWithCommas() que acepte de uno a
cinco enteros, y luego devuelva un string con esos números separados por comas.
Aquí tienes algunos ejemplos de llamadas a funciones y valores devueltos:
| Llamada a función | Valor devuelto |
|---|---|
joinWithCommas(1) | '1' |
joinWithCommas(1, 2, 3) | '1,2,3' |
joinWithCommas(1, 1, 1, 1, 1) | '1,1,1,1,1' |
Solución para el ejemplo de parámetros posicionales
Los parámetros b, c, d y e son null si el llamador no los proporciona.
Lo importante, entonces, es verificar si esos argumentos son null
antes de agregarlos al string final.
String joinWithCommas(int a, [int? b, int? c, int? d, int? e]) {
var total = '$a';
if (b != null) total = '$total,$b';
if (c != null) total = '$total,$c';
if (d != null) total = '$total,$d';
if (e != null) total = '$total,$e';
return total;
}
Parámetros nombrados
#Utilizando la sintaxis de llaves al final de la lista de parámetros, Puedes definir parámetros que tengan nombres.
Los parámetros nombrados son opcionales
a menos que estén marcados explícitamente como required.
void printName(String firstName, String lastName, {String? middleName}) {
print('$firstName ${middleName ?? ''} $lastName');
}
void main() {
printName('Dash', 'Dartisan');
printName('John', 'Smith', middleName: 'Who');
// Named arguments can be placed anywhere in the argument list.
printName('John', middleName: 'Who', 'Smith');
}
Como era de esperar,
el valor predeterminado de un parámetro nombrado que admite valores nulos es null,
pero puedes proporcionar un valor predeterminado personalizado.
Si el tipo de un parámetro no admite valores nulos,
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 del constructor).
void printName(String firstName, String lastName, {String middleName = ''}) {
print('$firstName $middleName $lastName');
}
Una función no puede tener parámetros opcionales posicionales y nombrados a la vez.
Ejercicio
#Añade un método de instancia copyWith() a la clase MyDataObject
. Debería tomar tres parámetros nombrados que admitan valores nulos:
int? newIntString? newStringdouble? newDouble
Tu método copyWith() debería devolver un nuevo MyDataObject
basado en la instancia actual,
con los datos de los parámetros anteriores (si los hay)
copiados en las propiedades del objeto.
Por ejemplo, si newInt no es nulo,
entonces copia su valor en anInt.
Ignora todos los errores iniciales en el DartPad.
Solución para el ejemplo de parámetros nombrados
El método copyWith aparece en muchas clases y librerías.
El tuyo debería hacer varias cosas:
usar parámetros nombrados opcionales,
crear una nueva instancia de MyDataObject,
y usar los datos de los parámetros para rellenarla
(o los datos de la instancia actual si los parámetros son nulos).
¡Esta es una oportunidad para practicar más con el operador ??!
MyDataObject copyWith({int? newInt, String? newString, double? newDouble}) {
return MyDataObject(
anInt: newInt ?? this.anInt,
aString: newString ?? this.aString,
aDouble: newDouble ?? this.aDouble,
);
}
Excepciones
#El código Dart puede lanzar y capturar excepciones. A diferencia de Java, todas las excepciones de Dart no son comprobadas (unchecked). Los métodos no declaran qué excepciones podrían lanzar y no es obligatorio capturar ninguna excepción.
Dart proporciona los tipos Exception y Error, pero se permite
lanzar cualquier objeto no nulo:
throw Exception('Something bad happened.');
throw 'Waaaaaaah!';
Usa las palabras clave try, on y catch al manejar excepciones:
try {
breedMoreLlamas();
} on OutOfLlamasException {
// A specific exception
buyMoreLlamas();
} on Exception catch (e) {
// Anything else that is an exception
print('Unknown exception: $e');
} catch (e) {
// No specified type, handles all
print('Something really unknown: $e');
}
La palabra clave try funciona como en la mayoría de los demás lenguajes.
Usa la palabra clave on para filtrar excepciones específicas por tipo,
y la palabra clave catch para obtener una referencia al objeto de la excepción.
Si no puedes manejar completamente la excepción, usa la palabra clave rethrow
para propagar la excepción:
try {
breedMoreLlamas();
} catch (e) {
print('I was just trying to breed llamas!');
rethrow;
}
Para ejecutar código tanto si se lanza una excepción como si no,
usa finally:
try {
breedMoreLlamas();
} catch (e) {
// ... handle exception ...
} finally {
// Always clean up, even if an exception is thrown.
cleanLlamaStalls();
}
Ejercicio
#Implementa tryFunction() a continuación. Debería ejecutar un método no confiable y
luego hacer lo siguiente:
- Si
untrustworthy()lanza unaExceptionWithMessage, llama alogger.logExceptioncon el tipo de excepción y el mensaje (intenta usaronycatch). - Si
untrustworthy()lanza unaException, llama alogger.logExceptioncon el tipo de excepción (intenta usaronpara este caso). - Si
untrustworthy()lanza cualquier otro objeto, no captures la excepción. - Después de que todo sea capturado y manejado, llama a
logger.doneLogging(intenta usarfinally).
Solución para el ejemplo de excepciones
Este ejercicio parece complicado, pero en realidad es una gran sentencia try.
Llama a untrustworthy dentro del try, y
luego usa on, catch y finally para capturar excepciones y
llamar a métodos en el logger.
void tryFunction(VoidFunction untrustworthy, Logger logger) {
try {
untrustworthy();
} on ExceptionWithMessage catch (e) {
logger.logException(e.runtimeType, e.message);
} on Exception {
logger.logException(Exception);
} finally {
logger.doneLogging();
}
}
Uso de this en un constructor
#
Dart proporciona un atajo práctico para asignar
valores a las propiedades en un constructor:
usa this.propertyName al declarar el constructor:
class MyColor {
int red;
int green;
int blue;
MyColor(this.red, this.green, this.blue);
}
final color = MyColor(80, 80, 128);
Esta técnica también funciona para parámetros nombrados. Los nombres de las propiedades se convierten en los nombres de los parámetros:
class MyColor {
// ...
MyColor({required this.red, required this.green, required this.blue});
}
final color = MyColor(red: 80, green: 80, blue: 80);
En el código anterior, red, green y blue se marcan como required
porque estos valores int no pueden ser null.
Si agregas valores predeterminados, puedes omitir required:
MyColor([this.red = 0, this.green = 0, this.blue = 0]);
// or
MyColor({this.red = 0, this.green = 0, this.blue = 0});
Ejercicio
#Añade un constructor de una sola 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 el DartPad.
Solución para el ejemplo de `this`
Este ejercicio tiene una solución de una sola línea.
Declara el constructor con
this.anInt, this.aString y this.aDouble
como sus parámetros en ese orden.
MyClass(this.anInt, this.aString, this.aDouble);
Listas de inicialización
#A veces, cuando implementas un constructor, necesitas realizar cierta 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. Realiza este trabajo en una lista de inicialización, que se coloca entre la firma del constructor y su cuerpo:
Point.fromJson(Map<String, double> json) : x = json['x']!, y = json['y']! {
print('In Point.fromJson(): ($x, $y)');
}
La lista de inicialización también es un lugar conveniente para colocar asserts, que se ejecutan solo durante el desarrollo:
NonNegativePoint(this.x, this.y) : assert(x >= 0), assert(y >= 0) {
print('I just made a NonNegativePoint: ($x, $y)');
}
Ejercicio
#Completa el constructor FirstTwoLetters a continuación.
Usa una lista de inicialización para asignar los dos primeros caracteres de word a
las propiedades letterOne y LetterTwo.
Como mérito adicional, añade un assert para detectar palabras de menos de dos caracteres.
Ignora todos los errores iniciales en el DartPad.
Solución para el ejemplo de listas de inicialización
Deben realizarse dos asignaciones:
a letterOne se le debe asignar word[0],
y a letterTwo se le debe asignar word[1].
FirstTwoLetters(String word)
: assert(word.length >= 2),
letterOne = word[0],
letterTwo = word[1];
Constructores nombrados
#Para permitir que las clases tengan múltiples constructores, Dart admite constructores nombrados:
class Point {
double x, y;
Point(this.x, this.y);
Point.origin() : x = 0, y = 0;
}
Para usar un constructor nombrado, invócalo usando su nombre completo:
final myPoint = Point.origin();
Ejercicio
#Dale a la clase Color un constructor llamado Color.black
que establezca las tres propiedades a cero.
Ignora todos los errores iniciales en el DartPad.
Solución para el ejemplo de constructores nombrados
La declaración de tu constructor debe comenzar con Color.black():.
En la lista de inicialización (después de los dos puntos),
establece red, green y blue en 0.
Color.black() : red = 0, green = 0, blue = 0;
Constructores de tipo factory
#Dart admite constructores de fábrica,
los cuales pueden devolver subtipos o incluso null.
Para crear un constructor de fábrica, usa la palabra clave factory:
class Square extends Shape {}
class Circle extends Shape {}
class Shape {
Shape();
factory Shape.fromTypeName(String typeName) {
if (typeName == 'square') return Square();
if (typeName == 'circle') return Circle();
throw ArgumentError('Unrecognized $typeName');
}
}
Ejercicio
#Reemplaza la línea TODO(); en el constructor de fábrica
llamado IntegerHolder.fromList para devolver lo siguiente:
- Si la lista tiene un valor,
crea una instancia de
IntegerSingleutilizando ese valor. - Si la lista tiene dos valores,
crea una instancia de
IntegerDoubleutilizando los valores en orden. - Si la lista tiene tres valores,
crea una instancia de
IntegerTripleutilizando los valores en orden. - De lo contrario, lanza un
Error.
Si tienes éxito, la consola debería mostrar Success!.
Solución para el ejemplo de constructores de fábrica
Dentro del constructor de fábrica,
verifica la longitud de la lista, luego crea y devuelve un
IntegerSingle, IntegerDouble o IntegerTriple según corresponda.
Reemplaza TODO(); con el siguiente bloque de código.
switch (list.length) {
case 1:
return IntegerSingle(list[0]);
case 2:
return IntegerDouble(list[0], list[1]);
case 3:
return IntegerTriple(list[0], list[1], list[2]);
default:
throw ArgumentError("List must between 1 and 3 items. This list was ${list.length} items.");
}
Constructores redireccionados
#A veces, el único propósito de un constructor es redirigir a
otro constructor en la misma clase.
El cuerpo de un constructor de redirección está vacío,
y la llamada al constructor aparece después de dos puntos (:).
class Automobile {
String make;
String model;
int mpg;
// The main constructor for this class.
Automobile(this.make, this.model, this.mpg);
// Delegates to the main constructor.
Automobile.hybrid(String make, String model) : this(make, model, 60);
// Delegates to a named constructor
Automobile.fancyHybrid() : this.hybrid('Futurecar', 'Mark 2');
}
Ejercicio
#¿Recuerdas la clase Color de arriba? Crea un constructor nombrado llamado
black, pero en lugar de asignar las propiedades manualmente, redirígelo al
constructor predeterminado con ceros como argumentos.
Ignora todos los errores iniciales en el DartPad.
Solución para el ejemplo de redirección de constructores
Tu constructor debería redirigir a this(0, 0, 0).
Color.black() : this(0, 0, 0);
Constructores const
#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.
class ImmutablePoint {
static const ImmutablePoint origin = ImmutablePoint(0, 0);
final int x;
final int y;
const ImmutablePoint(this.x, this.y);
}
Ejercicio
#Modifica la clase Recipe para que sus instancias puedan ser constantes
y crea un constructor constante que haga lo siguiente:
- Tenga tres parámetros:
ingredients,calories, ymilligramsOfSodium(en ese orden). - Use la sintaxis
this.para asignar automáticamente los valores de los parámetros a las propiedades del objeto con el mismo nombre. - Sea constante, con la palabra clave
constjusto antes deRecipeen la declaración del constructor.
Ignora todos los errores iniciales en el DartPad.
Solución para el ejemplo de constructores const
Para que el constructor sea const, deberás hacer que todas las propiedades sean final.
class Recipe {
final List<String> ingredients;
final int calories;
final double milligramsOfSodium;
const Recipe(this.ingredients, this.calories, this.milligramsOfSodium);
}
¿Qué sigue?
#Esperamos que hayas disfrutado usando este tutorial para aprender o poner a prueba tus conocimientos sobre algunas de las características más interesantes del lenguaje Dart.
Lo que puedes intentar a continuación incluye:
- Lee el Dart language tour.
- Juega con DartPad.
- Obtén el SDK de Dart.
A menos que se indique lo contrario, la documentación de este sitio refleja Dart 3.12.2. Página actualizada por última vez el 02-02-2026. Ver fuente oreportar un problema.