← Dart EspañolChapter 10 of 13

Seguridad Null

## Objetivos de Aprendizaje - Comprender la seguridad null en Dart - Dominar tipos anulables - Usar operadores nulos - Trabajar con variables late ## Por Que Seguridad Null? ### El Problema ```dart // Sin seguridad null String? name; // Puede ser null print(name.length); // Error en tiempo de ejecucion si es null! ``` ### La Solucion de Dart ```dart // Con seguridad null - detectado en tiempo de compilacion String name = 'Alice'; // No puede ser null // name = null; // Error! String? optional; // Anulable optional = null; // OK // print(optional.length); // Error! No se puede acceder sin verificacion null ``` ## Tipos Anulables ### Sintaxis Basica ```dart void main() { // No anulable (debe tener valor) String name = 'Alice'; // Anulable (puede ser null) String? nullable; nullable = null; // OK nullable = 'Bob'; // OK } ``` ### Se Requiere Verificacion Null ```dart void main() { String? nullable; // Error: nullable no puede asignarse a no anulable // String mustNotBeNull = nullable; // Solucion 1: Verificar si es null if (nullable != null) { String definitelyNotNull = nullable; // OK print(definitelyNotNull.length); } // Solucion 2: Usar operadores para anulables directamente print(nullable?.length); // null (acceso seguro) } ``` ## Operadores Nulos ### Acceso Nulo (?) ```dart void main() { String? name; print(name?.length); // null (no lanza excepcion) name = 'Alice'; print(name?.length); // 5 } ``` ### Asignacion Nula (??=) ```dart void main() { String? name; name ??= 'Por Defecto'; // Solo asigna si es null print(name); // Por Defecto name = 'Alice'; name ??= 'Por Defecto'; // Sin efecto ya que no es null print(name); // Alice } ``` ### Indice Nulo ([]?) ```dart void main() { List? numbers = [1, 2, 3]; print(numbers?[0]); // 1 numbers = null; print(numbers?[0]); // null } ``` ### Operador If-null (??) ```dart void main() { String? name; // Devuelve izquierda si no es null, si no derecha String displayName = name ?? 'Invitado'; print(displayName); // Invitado name = 'Alice'; displayName = name ?? 'Invitado'; print(displayName); // Alice } ``` ### Invocacion de Metodo Nula ```dart void main() { String? text; // Solo invoca si no es null text?.toUpperCase(); // null text = 'hola'; text?.toUpperCase(); // HOLA } ``` ## Desenvoltura Forzada (!) ### Cuando Usar ```dart void main() { String? name = 'Alice'; // Usar ! cuando estas seguro de que no es null // Solo usar si has verificado o sabes que esta garantizado print(name!.length); // 5 // Peligro! String? danger; // print(danger!.length); // Error en tiempo de ejecucion! } ``` ### Patron para Non-null Conocido ```dart void main() { String? compute() { // ... logica compleja que siempre devuelve no null return 'resultado'; } String result = compute()!; // Seguro si confias en la logica print(result.length); } ``` ## Variables Late ### Uso Basico ```dart late String description; void init() { description = 'Inicializado'; } void main() { // print(description); // Error si se accede antes de init() init(); print(description); // Inicializado } ``` ### Con Final ```dart late final String config; void load() { config = 'Cargado'; } void main() { load(); print(config); // Cargado } ``` ### Inicializacion Perezosa ```dart late String expensive = compute(); String compute() { print('Calculando...'); return 'Resultado'; } void main() { // expensive aun no se ha calculado print('Antes del acceso'); print(expensive); // Calculando... Resultado } ``` ### Casos de Uso ```dart class User { late String displayName; User(Map data) { // Operacion costosa diferida displayName = data['name'] ?? 'Desconocido'; } } ``` ## Seguridad Null en Funciones ### Parametros ```dart // Parametro anulable void greet(String? name) { if (name != null) { print('Hola, $name'); } } // No anulable requerido void greetRequired(String name) { print('Hola, $name'); } void main() { greet(null); // OK greet('Alice'); // OK // greetRequired(null); // Error! greetRequired('Alice'); // OK } ``` ### Tipos de Retorno ```dart // Retorno anulable String? findName() { return 'Alice'; // o return null; } // Retorno no anulable (siempre debe devolver valor) String findGreeting() { return 'Hola'; } ``` ## Seguridad Null en Clases ### Campos Anulables ```dart class User { String name; String? email; // Anulable User(this.name, [this.email]); } void main() { var user = User('Alice', 'alice@email.com'); print(user.email); // alice@email.com var user2 = User('Bob'); print(user2.email); // null } ``` ### Campos Late ```dart class DataService { late String data; Future load() async { data = await fetchData(); } } ``` ### Campos Anulables con Late ```dart class Config { late String? cachedData; void load() { cachedData = fetch(); } String? get() { return cachedData; } } ``` ## Seguridad Null en Colecciones ### Elementos Anulables ```dart void main() { // Lista de cadenas anulables List items = ['a', null, 'b', null, 'c']; for (var item in items) { if (item != null) { print(item.toUpperCase()); } } } ``` ### Coleccion Anulable ```dart void main() { // Lista anulable List? nullableList; print(nullableList?.length); // null nullableList = [1, 2, 3]; print(nullableList?.length); // 3 } ``` ## Seguridad Null en Genericos ### Argumentos de Tipo Anulables ```dart void main() { // List - lista de cadenas anulables List nullableStrings = ['a', null, 'b']; // List? - lista anulable de cadenas List? optionalList; // Map - claves y valores anulables Map mixed = {null: 0, 'a': 1}; } ``` ## No Anulable por Defecto en Dart 3 ### Parametros Nombrados Requeridos ```dart void createUser({ required String name, String? email, // Opcional int age = 0, }) { print('$name, $email, $age'); } void main() { createUser(name: 'Alice'); // OK // createUser(); // Error: name es requerido } ``` ## Mejores Practicas ### 1. Preferir Tipos No Anulables ```dart // Mal String? name = 'Alice'; // Bien String name = 'Alice'; ``` ### 2. Usar Late con Moderacion ```dart // Solo cuando es necesario late String data; // Mejor si puedes usar el constructor Data(this.data); // preferido ``` ### 3. Usar Verificaciones Null ```dart // Antes de acceder a anulable if (value != null) { value.someMethod(); } // O usar operadores seguros value?.someMethod(); ``` ### 4. Proporcionar Valores por Defecto ```dart // Con operador ?? String display = name ?? 'Desconocido'; // Con ??= para mutables name ??= 'Por Defecto'; ``` ## Resumen - Dart es seguro para null por defecto - Sufijo `?` hace el tipo anulable - `?.` acceso seguro a propiedades - `??` operador if-null - `??=` asignacion nula - `!` desenvolvimiento forzado (usar con cuidado) - `late` difiere la inicializacion - La seguridad null previene errores de null en tiempo de ejecucion en tiempo de compilacion

Comments

Comments powered by Giscus

To enable comments, add your Giscus embed code here.

Learn more about Giscus →