dart:core
Aprende sobre las características principales de la biblioteca dart:core de Dart.
La biblioteca dart:core (referencia de la API) proporciona un conjunto pequeño pero crítico de funcionalidad integrada. Esta biblioteca se importa automáticamente en cada programa de Dart.
Imprimir en la consola
#El método de nivel superior print() toma un solo argumento (cualquier Object)
y muestra el valor de cadena de ese objeto (tal como lo devuelve toString())
en la consola.
print(anObject);
print('I drink $tea.');
Para obtener más información sobre cadenas básicas y toString(), consulta
Cadenas en el recorrido del lenguaje.
Numbers
#La biblioteca dart:core define las clases num, int y double, las cuales tienen algunas utilidades básicas para trabajar con números.
Puedes convertir una cadena en un entero o un double con los métodos parse()
de int y double, respectivamente:
assert(int.parse('42') == 42);
assert(int.parse('0x42') == 66);
assert(double.parse('0.50') == 0.5);
O bien, usa el método parse() de num, el cual crea un entero si es posible y, de lo contrario, un double:
assert(num.parse('42') is int);
assert(num.parse('0x42') is int);
assert(num.parse('0.50') is double);
Para especificar la base de un entero, agrega un parámetro radix:
assert(int.parse('42', radix: 16) == 66);
Usa el método toString() para convertir un
int o un double en una cadena. Para especificar el número de dígitos a la derecha
del punto decimal, usa toStringAsFixed().
Para especificar el
número de dígitos significativos en la cadena, usa
toStringAsPrecision():
// Convert an int to a string.
assert(42.toString() == '42');
// Convert a double to a string.
assert(123.456.toString() == '123.456');
// Specify the number of digits after the decimal.
assert(123.456.toStringAsFixed(2) == '123.46');
// Specify the number of significant figures.
assert(123.456.toStringAsPrecision(2) == '1.2e+2');
assert(double.parse('1.2e+2') == 120.0);
Para obtener más información, consulta la documentación de la API para int, double y num. Consulta también la sección de dart:math
Cadenas y expresiones regulares
#Una cadena en Dart es una secuencia inmutable de unidades de código UTF-16. El recorrido del lenguaje tiene más información sobre las cadenas. Puedes usar expresiones regulares (objetos RegExp) para buscar dentro de las cadenas y reemplazar partes de ellas.
La clase String define métodos como split(), contains(),
startsWith(), endsWith(), y más.
Buscar dentro de una cadena
#Puedes encontrar ubicaciones particulares dentro de una cadena, así como verificar si una cadena comienza o termina con un patrón particular. Por ejemplo:
// Check whether a string contains another string.
assert('Never odd or even'.contains('odd'));
// Does a string start with another string?
assert('Never odd or even'.startsWith('Never'));
// Does a string end with another string?
assert('Never odd or even'.endsWith('even'));
// Find the location of a string inside a string.
assert('Never odd or even'.indexOf('odd') == 6);
Extraer datos de una cadena
#Puedes obtener los caracteres individuales de una cadena como Strings o ints, respectivamente. Para ser precisos, en realidad obtienes unidades de código UTF-16 individuales; los caracteres con números altos, como el símbolo de la clave de sol ('\u{1D11E}'), representan dos unidades de código cada uno.
También puedes extraer una subcadena o dividir una cadena en una lista de subcadenas:
// Grab a substring.
assert('Never odd or even'.substring(6, 9) == 'odd');
// Split a string using a string pattern.
var parts = 'progressive web apps'.split(' ');
assert(parts.length == 3);
assert(parts[0] == 'progressive');
// Get a UTF-16 code unit (as a string) by index.
assert('Never odd or even'[0] == 'N');
// Use split() with an empty string parameter to get
// a list of all characters (as Strings); good for
// iterating.
for (final char in 'hello'.split('')) {
print(char);
}
// Get all the UTF-16 code units in the string.
var codeUnitList = 'Never odd or even'.codeUnits.toList();
assert(codeUnitList[0] == 78);
:::
En muchos casos, querrás trabajar con
grupos de grafemas de Unicode
en lugar de unidades de código puras.
Estos son caracteres tal como los percibe
el usuario (por ejemplo, "🇬🇧" es un
carácter percibido por el usuario pero representa varias
unidades de código UTF-16).
Para esto, el equipo de Dart proporciona el
paquete characters.
:::
Convertir a mayúsculas o minúsculas
#Puedes convertir fácilmente cadenas a sus variantes en mayúsculas y minúsculas:
// Convert to uppercase.
assert('web apps'.toUpperCase() == 'WEB APPS');
// Convert to lowercase.
assert('WEB APPS'.toLowerCase() == 'web apps');
Recortar y cadenas vacías
#Elimina todos los espacios en blanco iniciales y finales con trim(). Para verificar
si una cadena está vacía (la longitud es cero), usa isEmpty.
// Trim a string.
assert(' hello '.trim() == 'hello');
// Check whether a string is empty.
assert(''.isEmpty);
// Strings with only white space are not empty.
assert(' '.isNotEmpty);
Reemplazar parte de una cadena
#Las cadenas son objetos inmutables, lo que significa que puedes crearlos pero no puedes
cambiarlos. Si observas de cerca la referencia de la API de String,
notarás que
ninguno de los métodos cambia realmente el estado de un String. Por ejemplo,
el método replaceAll() devuelve un nuevo String sin cambiar el
String original:
var greetingTemplate = 'Hello, NAME!';
var greeting = greetingTemplate.replaceAll(RegExp('NAME'), 'Bob');
// greetingTemplate didn't change.
assert(greeting != greetingTemplate);
Construir una cadena
#Para generar mediante programación una cadena, puedes usar StringBuffer. Un
StringBuffer no genera un nuevo objeto String hasta que se llama a toString().
El método writeAll() tiene un segundo parámetro opcional que
te permite especificar un separador—en este caso, un espacio.
var sb = StringBuffer();
sb
..write('Use a StringBuffer for ')
..writeAll(['efficient', 'string', 'creation'], ' ')
..write('.');
var fullString = sb.toString();
assert(fullString == 'Use a StringBuffer for efficient string creation.');
Expresiones regulares
#La clase RegExp proporciona las mismas capacidades que las expresiones regulares de JavaScript. Usa expresiones regulares para búsquedas eficientes y coincidencia de patrones en cadenas.
// Here's a regular expression for one or more digits.
var digitSequence = RegExp(r'\d+');
var lettersOnly = 'llamas live fifteen to twenty years';
var someDigits = 'llamas live 15 to 20 years';
// contains() can use a regular expression.
assert(!lettersOnly.contains(digitSequence));
assert(someDigits.contains(digitSequence));
// Replace every match with another string.
var exedOut = someDigits.replaceAll(digitSequence, 'XX');
assert(exedOut == 'llamas live XX to XX years');
También puedes trabajar directamente con la clase RegExp. La clase Match proporciona acceso a una coincidencia de expresión regular.
var digitSequence = RegExp(r'\d+');
var someDigits = 'llamas live 15 to 20 years';
// Check whether the reg exp has a match in a string.
assert(digitSequence.hasMatch(someDigits));
// Loop through all matches.
for (final match in digitSequence.allMatches(someDigits)) {
print(match.group(0)); // 15, then 20
}
Más información
#Consulta la referencia de la API de String para obtener una lista completa de métodos. Consulta también la referencia de la API para StringBuffer, Pattern, RegExp, y Match.
Colecciones
#Dart incluye una API principal de colecciones, que incluye clases para listas, conjuntos y mapas.
Listas
#Como muestra el recorrido del lenguaje, puedes usar literales para crear e inicializar listas. Alternativamente, usa uno de los constructores de List. La clase List también define varios métodos para agregar elementos a las listas y eliminarlos de ellas.
// Create an empty list of strings.
var grains = <String>[];
assert(grains.isEmpty);
// Create a list using a list literal.
var fruits = ['apples', 'oranges'];
// Add to a list.
fruits.add('kiwis');
// Add multiple items to a list.
fruits.addAll(['grapes', 'bananas']);
// Get the list length.
assert(fruits.length == 5);
// Remove a single item.
var appleIndex = fruits.indexOf('apples');
fruits.removeAt(appleIndex);
assert(fruits.length == 4);
// Remove all elements from a list.
fruits.clear();
assert(fruits.isEmpty);
// You can also create a List using one of the constructors.
var vegetables = List.filled(99, 'broccoli');
assert(vegetables.every((v) => v == 'broccoli'));
Usa indexOf() para encontrar el índice de un objeto en una lista:
var fruits = ['apples', 'oranges'];
// Access a list item by index.
assert(fruits[0] == 'apples');
// Find an item in a list.
assert(fruits.indexOf('apples') == 0);
Ordena una lista usando el método sort(). Puedes proporcionar una función de
ordenamiento que compare dos objetos. Esta función de ordenamiento debe devolver <
0 para el menor, 0 para el mismo y > 0 para el mayor. El siguiente
ejemplo utiliza compareTo(), el cual está definido por
Comparable e implementado por String.
var fruits = ['bananas', 'apples', 'oranges'];
// Sort a list.
fruits.sort((a, b) => a.compareTo(b));
assert(fruits[0] == 'apples');
Las listas son tipos parametrizados (genéricos), por lo que puedes especificar el tipo que debe contener una lista:
// This list should contain only strings.
var fruits = <String>[];
fruits.add('apples');
var fruit = fruits[0];
assert(fruit is String);
fruits.add(5); // Error: 'int' can't be assigned to 'String'
Consulta la referencia de la API de List para obtener una lista completa de métodos.
Sets
#Un conjunto en Dart es una colección desordenada de elementos únicos. Debido a que un conjunto está desordenado, no puedes obtener los elementos de un conjunto por su índice (posición).
// Create an empty set of strings.
var ingredients = <String>{};
// Add new items to it.
ingredients.addAll(['gold', 'titanium', 'xenon']);
assert(ingredients.length == 3);
// Adding a duplicate item has no effect.
ingredients.add('gold');
assert(ingredients.length == 3);
// Remove an item from a set.
ingredients.remove('gold');
assert(ingredients.length == 2);
// You can also create sets using
// one of the constructors.
var atomicNumbers = Set.from([79, 22, 54]);
Usa contains() y containsAll() para verificar si uno o más
objetos están en un conjunto:
var ingredients = Set<String>();
ingredients.addAll(['gold', 'titanium', 'xenon']);
// Check whether an item is in the set.
assert(ingredients.contains('titanium'));
// Check whether all the items are in the set.
assert(ingredients.containsAll(['titanium', 'xenon']));
Una intersección es un conjunto cuyos elementos están en otros dos conjuntos.
var ingredients = Set<String>();
ingredients.addAll(['gold', 'titanium', 'xenon']);
// Create the intersection of two sets.
var nobleGases = Set.from(['xenon', 'argon']);
var intersection = ingredients.intersection(nobleGases);
assert(intersection.length == 1);
assert(intersection.contains('xenon'));
Consulta la referencia de la API de Set para obtener una lista completa de métodos.
Maps
#Un mapa, comúnmente conocido como diccionario o hash, es una colección desordenada de pares clave-valor. Los mapas asocian una clave a algún valor para una fácil recuperación. A diferencia de JavaScript, los objetos de Dart no son mapas.
Puedes declarar un mapa usando una sintaxis literal concisa, o puedes usar un constructor tradicional:
// Maps often use strings as keys.
var hawaiianBeaches = {
'Oahu': ['Waikiki', 'Kailua', 'Waimanalo'],
'Big Island': ['Wailea Bay', 'Pololu Beach'],
'Kauai': ['Hanalei', 'Poipu'],
};
// Maps can be built from a constructor.
var searchTerms = Map();
// Maps are parameterized types; you can specify what
// types the key and value should be.
var nobleGases = Map<int, String>();
Agregas, obtienes y estableces elementos del mapa usando la sintaxis de corchetes. Usa remove()
para eliminar una clave y su valor de un mapa.
var nobleGases = {54: 'xenon'};
// Retrieve a value with a key.
assert(nobleGases[54] == 'xenon');
// Check whether a map contains a key.
assert(nobleGases.containsKey(54));
// Remove a key and its value.
nobleGases.remove(54);
assert(!nobleGases.containsKey(54));
Puedes recuperar todos los valores o todas las claves de un mapa:
var hawaiianBeaches = {
'Oahu': ['Waikiki', 'Kailua', 'Waimanalo'],
'Big Island': ['Wailea Bay', 'Pololu Beach'],
'Kauai': ['Hanalei', 'Poipu'],
};
// Get all the keys as an unordered collection
// (an Iterable).
var keys = hawaiianBeaches.keys;
assert(keys.length == 3);
assert(keys.contains('Oahu'));
// Get all the values as an unordered collection
// (an Iterable of Lists).
var values = hawaiianBeaches.values;
assert(values.length == 3);
assert(values.any((v) => v.contains('Waikiki')));
Para verificar si un mapa contiene una clave, usa containsKey(). Debido a que los valores del
mapa pueden ser null, no puedes confiar en simplemente obtener el valor de la
clave y verificar si es null para determinar la existencia de una clave.
var hawaiianBeaches = {
'Oahu': ['Waikiki', 'Kailua', 'Waimanalo'],
'Big Island': ['Wailea Bay', 'Pololu Beach'],
'Kauai': ['Hanalei', 'Poipu'],
};
assert(hawaiianBeaches.containsKey('Oahu'));
assert(!hawaiianBeaches.containsKey('Florida'));
Usa el método putIfAbsent() cuando desees asignar un valor a una clave
si y solo si la clave aún no existe en el mapa. Debes proporcionar
una función que devuelva el valor.
var teamAssignments = <String, String>{};
teamAssignments.putIfAbsent('Catcher', () => pickToughestKid());
assert(teamAssignments['Catcher'] != null);
Consulta la referencia de la API de Map para obtener una lista completa de métodos.
Métodos comunes de colecciones
#List, Set y Map comparten funcionalidad común que se encuentra en muchas colecciones. Parte de esta funcionalidad común está definida por la clase Iterable, la cual List y Set implementan.
Usa isEmpty o isNotEmpty para verificar si una lista, conjunto o mapa tiene elementos:
var coffees = <String>[];
var teas = ['green', 'black', 'chamomile', 'earl grey'];
assert(coffees.isEmpty);
assert(teas.isNotEmpty);
Para aplicar una función a cada elemento de una lista, conjunto o mapa, puedes usar
forEach():
var teas = ['green', 'black', 'chamomile', 'earl grey'];
teas.forEach((tea) => print('I drink $tea'));
Cuando invocas forEach() en un mapa, tu función debe tomar dos
argumentos (la clave y el valor):
hawaiianBeaches.forEach((k, v) {
print('I want to visit $k and swim at $v');
// I want to visit Oahu and swim at
// [Waikiki, Kailua, Waimanalo], etc.
});
Las iterables proporcionan el método map(), el cual te brinda todos los resultados en
un solo objeto:
var teas = ['green', 'black', 'chamomile', 'earl grey'];
var loudTeas = teas.map((tea) => tea.toUpperCase());
loudTeas.forEach(print);
Para forzar a que tu función se llame inmediatamente en cada elemento, usa
map().toList() o map().toSet():
var loudTeas = teas.map((tea) => tea.toUpperCase()).toList();
Usa el método where() de Iterable para obtener todos los elementos que coinciden con una
condición. Usa los métodos any() y every() de Iterable para verificar si
algunos o todos los elementos coinciden con una condición.
var teas = ['green', 'black', 'chamomile', 'earl grey'];
// Chamomile is not caffeinated.
bool isDecaffeinated(String teaName) => teaName == 'chamomile';
// Use where() to find only the items that return true
// from the provided function.
var decaffeinatedTeas = teas.where((tea) => isDecaffeinated(tea));
// or teas.where(isDecaffeinated)
// Use any() to check whether at least one item in the
// collection satisfies a condition.
assert(teas.any(isDecaffeinated));
// Use every() to check whether all the items in a
// collection satisfy a condition.
assert(!teas.every(isDecaffeinated));
Para obtener una lista completa de métodos, consulta la referencia de la API de Iterable, así como las de List, Set y Map.
URIs
#La clase Uri proporciona
funciones para codificar y decodificar cadenas para su uso en URIs (que tal vez
conozcas como URLs). Estas funciones manejan caracteres que son especiales para
las URIs, como & y =. La clase Uri también analiza y expone los
componentes de una URI: host, puerto, esquema, etc.
Codificar y decodificar URIs completamente calificadas
#Para codificar y decodificar caracteres excepto aquellos que tienen un significado especial en una
URI (como /, :, &, #), usa los métodos
encodeFull() y
decodeFull(). Estos métodos son buenos para codificar o decodificar
una URI completamente calificada, dejando intactos los caracteres especiales de la URI.
var uri = 'https://example.org/api?foo=some message';
var encoded = Uri.encodeFull(uri);
assert(encoded == 'https://example.org/api?foo=some%20message');
var decoded = Uri.decodeFull(encoded);
assert(uri == decoded);
Observa cómo solo se codificó el espacio entre some y message.
Codificar y decodificar componentes de una URI
#Para codificar y decodificar todos los caracteres de una cadena que tienen un significado
especial en una URI, incluyendo (entre otros) /, & y
:, usa
los métodos encodeComponent() y decodeComponent().
var uri = 'https://example.org/api?foo=some message';
var encoded = Uri.encodeComponent(uri);
assert(
encoded == 'https%3A%2F%2Fexample.org%2Fapi%3Ffoo%3Dsome%20message',
);
var decoded = Uri.decodeComponent(encoded);
assert(uri == decoded);
Observa cómo se codifica cada carácter especial. Por ejemplo, / se
codifica como %2F.
Analizar URIs
#Si tienes un objeto Uri o una cadena de URI, puedes obtener sus partes utilizando
campos de Uri como path. Para crear un Uri a partir de una cadena, usa el
método estático parse():
var uri = Uri.parse('https://example.org:8080/foo/bar#frag');
assert(uri.scheme == 'https');
assert(uri.host == 'example.org');
assert(uri.path == '/foo/bar');
assert(uri.fragment == 'frag');
assert(uri.origin == 'https://example.org:8080');
Consulta la referencia de la API de Uri para ver más componentes de URI que puedes obtener.
Construir URIs
#Puedes construir una URI a partir de partes individuales usando el constructor Uri():
var uri = Uri(
scheme: 'https',
host: 'example.org',
path: '/foo/bar',
fragment: 'frag',
queryParameters: {'lang': 'dart'},
);
assert(uri.toString() == 'https://example.org/foo/bar?lang=dart#frag');
Si no necesitas especificar un fragmento,
para crear una URI con un esquema http o https,
puedes usar en su lugar los constructores de fábrica Uri.http
o Uri.https:
var httpUri = Uri.http('example.org', '/foo/bar', {'lang': 'dart'});
var httpsUri = Uri.https('example.org', '/foo/bar', {'lang': 'dart'});
assert(httpUri.toString() == 'http://example.org/foo/bar?lang=dart');
assert(httpsUri.toString() == 'https://example.org/foo/bar?lang=dart');
Fechas y horas
#Un objeto DateTime es un punto en el tiempo. La zona horaria es UTC o la zona horaria local.
Puedes crear objetos DateTime usando varios constructores y métodos:
// Get the current date and time.
var now = DateTime.now();
// Create a new DateTime with the local time zone.
var y2k = DateTime(2000); // January 1, 2000
// Specify the month and day.
y2k = DateTime(2000, 1, 2); // January 2, 2000
// Specify the date as a UTC time.
y2k = DateTime.utc(2000); // 1/1/2000, UTC
// Specify a date and time in ms since the Unix epoch.
y2k = DateTime.fromMillisecondsSinceEpoch(946684800000, isUtc: true);
// Parse an ISO 8601 date in the UTC time zone.
y2k = DateTime.parse('2000-01-01T00:00:00Z');
// Create a new DateTime from an existing one, adjusting just some properties:
var sameTimeLastYear = now.copyWith(year: now.year - 1);
La propiedad millisecondsSinceEpoch de una fecha devuelve el número de
miliseundos desde la "época Unix" — 1 de enero de 1970, UTC:
// 1/1/2000, UTC
var y2k = DateTime.utc(2000);
assert(y2k.millisecondsSinceEpoch == 946684800000);
// 1/1/1970, UTC
var unixEpoch = DateTime.utc(1970);
assert(unixEpoch.millisecondsSinceEpoch == 0);
Usa la clase Duration para calcular la diferencia entre dos fechas y desplazar una fecha hacia adelante o hacia atrás:
var y2k = DateTime.utc(2000);
// Add one year.
var y2001 = y2k.add(const Duration(days: 366));
assert(y2001.year == 2001);
// Subtract 30 days.
var december2000 = y2001.subtract(const Duration(days: 30));
assert(december2000.year == 2000);
assert(december2000.month == 12);
// Calculate the difference between two dates.
// Returns a Duration object.
var duration = y2001.difference(y2k);
assert(duration.inDays == 366); // y2k was a leap year.
Para obtener una lista completa de métodos, consulta la referencia de la API para DateTime y Duration.
Clases de utilidad
#La biblioteca principal contiene varias clases de utilidad, útiles para ordenar, mapear valores e iterar.
Comparar objetos
#Implementa la interfaz Comparable
para indicar que un objeto se puede comparar con otro objeto,
generalmente para ordenar. El método compareTo() devuelve < 0 para
menor, 0 para el mismo y > 0 para el mayor.
class Line implements Comparable<Line> {
final int length;
const Line(this.length);
@override
int compareTo(Line other) => length - other.length;
}
void main() {
var short = const Line(1);
var long = const Line(100);
assert(short.compareTo(long) < 0);
}
Implementar claves de mapa
#Cada objeto en Dart proporciona automáticamente un código hash entero y,
por lo tanto, se puede usar como clave en un mapa. Sin embargo, puedes sobrescribir el
getter hashCode para generar un código hash personalizado. Si lo haces, es posible que
también desees sobrescribir el operador ==. Los objetos que son iguales (a través de
==) deben tener códigos hash idénticos. Un código hash no tiene que ser
único, pero debe estar bien distribuido.
class Person {
final String firstName, lastName;
Person(this.firstName, this.lastName);
// Override hashCode using the static hashing methods
// provided by the `Object` class.
@override
int get hashCode => Object.hash(firstName, lastName);
// You should generally implement operator `==` if you
// override `hashCode`.
@override
bool operator ==(Object other) {
return other is Person &&
other.firstName == firstName &&
other.lastName == lastName;
}
}
void main() {
var p1 = Person('Bob', 'Smith');
var p2 = Person('Bob', 'Smith');
var p3 = 'not a person';
assert(p1.hashCode == p2.hashCode);
assert(p1 == p2);
assert(p1 != p3);
}
Iteración
#Las clases Iterable e Iterator admiten el acceso secuencial a una colección de valores. Para practicar el uso de estas colecciones, sigue el tutorial de colecciones de Iterable.
Si creas una clase que pueda proporcionar Iterators para su uso en bucles for-in, extiende (si es posible) o implementa Iterable. Implementa Iterator para definir la capacidad real de iteración.
class Process {
// Represents a process...
}
class ProcessIterator implements Iterator<Process> {
@override
Process get current => ...
@override
bool moveNext() => ...
}
// A mythical class that lets you iterate through all
// processes. Extends a subclass of [Iterable].
class Processes extends IterableBase<Process> {
@override
final Iterator<Process> iterator = ProcessIterator();
}
void main() {
// Iterable objects can be used with for-in.
for (final process in Processes()) {
// Do something with the process.
}
}
Excepciones
#La biblioteca principal de Dart define muchas excepciones y errores comunes. Las excepciones se consideran condiciones que puedes prever y capturar. Los errores son condiciones que no esperas ni planificas.
Un par de los errores más comunes son:
- NoSuchMethodError
-
Lanzado cuando un objeto receptor (que podría ser
null) no implementa un método. - ArgumentError
Puede ser lanzado por un método que encuentra un argumento inesperado.
Lanzar una excepción específica de la aplicación es una forma común de indicar que ha ocurrido un error. Puedes definir una excepción personalizada implementando la interfaz Exception:
class FooException implements Exception {
final String? msg;
const FooException([this.msg]);
@override
String toString() => msg ?? 'FooException';
}
Para más información, consulta Excepciones (en el recorrido del lenguaje) y la referencia de la API de Exception.
Referencias débiles y finalizadores
#Dart es un lenguaje con recolección de basura, lo que significa que cualquier objeto de Dart que no esté referenciado puede ser desechado por el recolector de basura. Este comportamiento predeterminado puede no ser deseable en algunos escenarios que involucran recursos nativos o si el objeto de destino no se puede modificar.
Una WeakReference almacena una referencia al objeto de destino que no afecta la forma en que el recolector de basura lo recopila. Otra opción es usar un Expando para agregar propiedades a un objeto.
Se puede usar un Finalizer para ejecutar una función callback después de que un objeto ya no esté referenciado. Sin embargo, no se garantiza la ejecución de este callback.
Un NativeFinalizer proporciona garantías más sólidas para interactuar con código nativo utilizando dart:ffi; su callback se invoca al menos una vez después de que el objeto ya no esté referenciado. Además, se puede utilizar para cerrar recursos nativos, como una conexión de base de datos o archivos abiertos.
Para garantizar que un objeto no sea recolectado por la basura y finalizado demasiado pronto, las clases pueden implementar la interfaz Finalizable. Cuando una variable local es Finalizable, no será recolectada por la basura hasta que haya terminado el bloque de código donde está declarada.
A menos que se indique lo contrario, la documentación en este sitio refleja Dart 3.12.2. Página actualizada por última vez el 31-05-2026. Ver fuente oreportar un problema.