Flutter DART variables - tipos de datos

De MediaWiki
Ir a la navegación Ir a la búsqueda

Introducción

  • Para aplicar los tipos de datos a variables necesitamos saber como definir variables en DART.
Para definir una variable anteponemos el tipo de dato a su nombre de la forma: tipo_dato nombre_variable;



Tipos de datos numéricos

  • Dart dispone de dos tipos de datos:
  • enteros (int) : desde -infinito a +infinito sin decimales.
  • decimales (double): desde -infinito a +infinito con decimales.


En la siguinte imagen podemos ver como implementa cada tipo de dato DART en el código nativo donde se vaya a ejecutar la aplicación.
Flutter dart tipo datos 1.JPG
Imagen obtenido de este sitio
  • Ejemplo de código:
void main() {
 
  int edad=15;
  double peso = 45.36;
  
  
  print("El alumno con edad $edad tiene un peso de $peso");
  
}
Comentarios:
  • Las variables están inicializadas en la definición.
  • Fijarse en la línea del print, como podemos emplear dentro de cadenas, variables definidas en Dart. Es necesasrio emplear el símbolo $nombrevariable. De esta forma nos ahorramos el tener que concatenar y convertir variables con tipos de datos diferentes.



Comparando tipos de datos numéricos

  • Indicar que Dart dispone de la función identical para determinal cuando dos números son iguales en valor y tipo.
El resultado varía si la aplicación se ejecuta en la Web y en otra plataforma (la implementación del tipo de dato double en la web es también int):
Flutter dart tipo datos 3.JPG
Imagen obtenida de esta web


Veamos un ejemplo, cuyo resultado es diferente si lo ejecutais en la Web o en el Android Studio:
void main(){

  int i_edad = 0;
  double d_edad  = 0.0;

  if (i_edad==d_edad) print('$i_edad es igual a $d_edad');

  if (!identical(i_edad,d_edad)) print('$i_edad no es idéntica a $d_edad');

}


Nota: Podemos emplear la función toStringAsFixed para mostrar un número de decimales concreto:
print('$i_edad es igual a ${d_edad.toStringAsFixed(1)}');
Fijarse que si lo hacemos dentro del print, necesitamos emplear las llaves (lo veremos posteriormente).


Nota: Existe otro tipo de dato, num que es el tipo del cual derivan int y double. Por lo tanto permite almacenar tanto valores enteros como decimales.

Antes de DART 2.1, si un número estaba definido como double, no podríamos asignar este valor: double var = 9; y tendríamos que poner: double var = 9.0;
En ese caso sería necesario definir la variable como num. A partir de DARt 2.1 esto ya no es necesario y acepta ese tipo de asignación.
Puede existir algún caso en el que sea necesario definir como num una variable, por ejemplo, si queremos llamar a una función con tipos de datos int/double (aunque sería más conveniente realizar un CAST).
void funcion(num val){
  print (val);
}

void main() {
 
  double num1 = 10.32;
  int num2 = 1;
  
  funcion(num1);
  funcion(num2);
}



Tipos de datos cadenas

  • Para definir una cadena, anteponemos al nombre de la variable el tipo de dato String.
Por ejemplo:
void main() {
 
  String nombre = 'Angel';
  String apellidos = 'Fernández González';
  
  String nombreCompleto = nombre + " " + apellidos;
  
  print("El nombre $nombre se junta con los apellidos $apellidos y forma $nombreCompleto");
}



Para concatenar cadenas podemos emplear:

  • Por interpolación, es decir, empleando el método print como vimos anteriormente.
  • Operador +: String cadena = 'cad1' + 'cad2';
  • Empleando literales de la forma: String cadena = 'cad1' 'cad2'; (sin espacio en blanco)

Tipos de datos booleanos

  • Al igual que en otros lenguajes de programación, para definir una variable booleana (que puede guardar valores true/false/null) la definimos de la siguiente forma:
void main() {
  
  bool encendido = true;
  
  if (encendido) {
    print('Está encendido.');
  }
  else{
    print('No está encendido');
  }
  
}
Nota:: Al escribir este código podéis comprobar como https://dartpad.de avisa en la parte else de que ese código no se va a ejecutar nunca (aparece subrayado y al situar el cursor en esa parte del código indica Dead Code.
Si quisiéramos probar a escribir por teclado un valor para determinar si es cierto o falso, tendríamos que ejecutar el siguiente código en el Android Studio u otro IDE de escritorio:
import 'dart:io';

void main() {

  bool encendido =  int.parse(stdin.readLineSync().toString()) == 1 ? true : false;

  if (encendido) {
    print('Está encendido.');
  }
  else{
    print('No está encendido');
  }

}



Tipos de datos dinámicos

  • Son variables de las cuales no sabemos que tipo de dato va a ser hasta que se asignen a un valor y cojerán el tipo de dato del valor asignado.


  • Podemos definirlas de tres formas:
  • Con la palabra reservada var.
  • Con la palabra reservada dynamic.
  • Con la palabra reservada Object.



Definidos con var

  • Podemos definir una variable con la sintaxis: var nombre_variable;
Si no inicializamos un valor, el tipo de dato asociado a estar variable será dynamic
Flutter dart tipo datos 2.JPG


Por ejemplo:
void main() {
 
  var nombre;
  
  nombre = "Angel"
  print(nombre);
  
}
En este caso, nombre no tiene asociado un tipo de dato. Al asignarle el valor "Angel" pasa a ser de tipo String, pero al no tener una asignación en la definición, podríamos asignarle un valor numérico y pasaría a ser un tipo de datos numérico.


Por ejemplo:
  var variable;
  
  variable = "Angel"; // Ahora es una cadena
  variable = 12;      // Ahora es un número
  variable = variable + 1;
  
  print(variable);
En el caso de dar un valor inicial, pasa a ser del tipo del valor asignado y ya no se podría cambiar por otro tipo, por lo que:
  var variable='Angel';  // Variable de tipo String => EQUIVALENTE A => String variable='Angel';

  variable = 10;   // ===> DARIA UN ERROR


Se recomienda la definición de variables de esta forma (con var y asignación de valor por defecto).



Definidos con dynamic

  • Tenemos que anteponer la palabra reservada dynamic antes del nombre de la variable.
Por ejemplo:
void main() {
  
  dynamic nosetipo='valor';

  
  if (nosetipo is dynamic) print ('Es dinámica');
  if (nosetipo is String) print ('Es una cadena');
  nosetipo = 1;
  if (nosetipo is int) print ('Es un número');
}


Por lo tanto si definimos una variable 'var' sin asignar valor o una variable 'dynamic', no habría diferencias entre ellas en cuanto a la asignación de valores de diferentes tipos.
Si definimos como tipo de un parámetro de una función var o dynamic no habrá diferencia.
void funcionPrueba(var param){
  // param puede ser de cualquier tipo, también podríamos definirlo como dynamic
}
void main() {
  
  funcionPrueba(1);
  funcionPrueba('cadena');
}


  • Cuando definimos métodos que devuelvan un tipo de dato desconocido (que pueda variar) debemos definirlos como dynamic, ya que si lo intentemos hacer con 'var' daría un error:
dynamic getDato(int tipo){
  if (tipo==1) return 'Devuelvo cadena';
  else return 100;  // Devuelvo número
  
  
}
void main() {
  
  
  dynamic valor = getDato(1);
  print('Valor es cadena: $valor');
  valor = getDato(0);
  print('Valor es número: $valor');
}



Definidos con Object

  • A diferencia de dynamic, con Object estamos indicando que lo que vamos a recibir será un objeto de una clase.
Por tanto podremos llamar a los métodos definidos en la clase Object (por ejemplo toString).
El caso anterior también funcionaría con Object:


Object getDato(int tipo){
  if (tipo==1) return 'Devuelvo cadena';
  else return 100;  // Devuelvo número
  
  
}
void main() {
  
  
  Object valor = getDato(1);
  print('Valor es cadena: $valor');
  valor = getDato(0);
  print('Valor es número: $valor');
}



Constantes

  • En DART tenemos dos modificadores para definir una constante:
  • const: Se inicializa en compilación.
  • final: Se inicializa en ejecución.
Por ejemplo:
void main() {
 
  const int numeroAlas = 10; // Se inicializa en compilación (antes de ejecución)
  final DateTime fechaActual = DateTime.now(); // Se inicializa en ejecución
  
  print (numeroAlas);
  print (fechaActual);
  
}

Nota: Indicar que podríamos ahorrarnos el poner el tipo de dato en la definición ya que asignaría el tipo de dato en base al valor por defecto.


En este ejemplo, no podríamos declarar la constante fechaActual como const ya que en compilación no podemos asignar la fecha actual.
Otra situación en la que se ve la diferencia entre los dos modificadores es cuando lo aplicamos a objetos de una clase.
Por ejemplo, si lo aplicamos a un Array (una lista), si definimos el array como const no podríamos añadir nuevos elementos a la lista (el objeto es inmutable).
Sin embargo, si lo definimos como final podríamos añadir o borrar valores a la lista.
void main() {

  final datos = <int>[1,2,3];
  print(datos);
  datos.add(4);
  print(datos);

  datos.remove(1);
  print(datos);
}
Flutter dart tipo datos 7.JPG


Sin embergo poniendo const, en Android Studio dará un unhandle exception (en la Web no continuará con la ejecución).
Flutter dart tipo datos 8.JPG






Conversión de tipos de datos

  • Cada tipo de dato tiene funciones que permite su conversión a otro tipo.
Lo más fácil es buscar cual es cuando se necesite.
Al poner un punto después de la variable, aparecen un conjunto de funciones que se pueden aplicar a dicho tipo.
Flutter dart tipo datos 6.JPG


Por ejemplo, para convertir un double a un int:
void main() {
 
  int val1 = 10;
  int val2 = 15;
  
  int resul = (val2/val1).toInt();
  print(resul);
  
}


  • También se puede hacer uso de los métodos parse de cada tipo de dato, como int.parse para convertir una cadena a un entero o double.parse para convertir una cadena a un double.
  • Para convertir a cadena podemos emplear los métodos toString() y toStringAsFixed si queremos guardar un número de dígitos decimales concreto.


Valores nulos

  • Cuando definimos una variable puede ser que no tengamos un valor que darle, y que,por tanto, sea desconocido.
Ese tipo de valor es lo que se conoce como valor null.
  • Normalmente se emplea en variables que pertenecen a una clase y que todavía no hemos instanciado.
DART incorpora un mecanimos de seguridad de empleo de valores nulos denomiado NULL SAFETY.


Este mecanimo impide que se pueda asignar un valor null a variables que no debeiran de poder guardar dicho valor.
Tener en cuenta que si a una variable le llega un valor null y no tenemos programado el uso con ese valor, normalmente el programa romperá y dejará de ejecutarse, pudiendo llegar a ser un problema de seguridad.
  • Veamos un ejemplo:
void main() {

  String cadena = 'Angel';

  cadena = null;

  print(cadena);

}
Flutter dart tipo datos 9.JPG
Este mecanimos puede ser muy útil cuando sepamos que no debería tener valores nulos una determinada variable, por ejemplo;
int getLength(String cadena){
  return cadena.length;
}

void main() {

  String cadena = 'Angel';
  print(getLength(null));
  
}
Como vemos, el método getLength() creado por mí, espera recibir una cadena, pero dicha cadena nunca va a poder ser null...


  • Si estamos trabajando en Web podemos inhabilitar el mecanimo de seguridad en la parte baja:
Flutter dart tipo datos 10.JPG

aunque no es recomendable hacerlo


  • Para solucionar el problema en caso de necesidad (es decir, que tenemos que definir una variable que sabemos que va a poder tener valores nulos) debemos de utilizar el símbolo intorrogación al lado del tipo de dato de la forma siguiente:
void main() {

  String? cadena = 'Angel';
  
  cadena = null;  
  print(cadena);  
}


  • Veamos otro ejemplo en la llamada a un método en el que indicamos que el parámetro va a poder recibir valores nulos:
void imprimirEstado(bool? valor){
  if (valor==true) { print('El valor es true'); }
  else if (valor == null) { print('El valor es null'); }
  else { print('El valor es false'); }
}

void main() {

  bool? encendido = true;  
  imprimirEstado(encendido);
  
  encendido = null;
  imprimirEstado(encendido);
  
}


  • Existen una serie de operadores que podemos emplear relacionados con el valor nulo:
  • Operador de aserción ! : Si sabemos seguro que una variable, a pesar de que acepta valores nulos, no va a tener un valor nulo, podemos asignarla a otra variable:
int? varPuedeTenerNulo=1;
int varSinNulo = 1;

void main(){

  varSinNulo = varPuedeTenerNulo!;  // Si no ponemos la admiración daría un error ya que no podemos asignar una variable que puede aceptar valores nulos a otra que no.
  
}
  • Operador consciente de nulos ? : Va pegado a una variable a la que queremos llamar a un metodo (al ser una variable que deriva de una Clase, y por tanto tenemos acceso a sus métodos) y sólo queremos que lo haga cuando la variable no sea nula.
String? varPuedeTenerNulo;

void main(){

  int? numCar = varPuedeTenerNulo?.length;  // length daría una excepción si la variable fuese nula
  print (numCar);
  
}
  • Operador ?? : Utilizado para asignar un valor a una varible, comprobando que el valor no sea nulo. Si es nulo, le asigna un valor especificado.
String? varPuedeTenerNulo;

void main(){

  String cadena = varPuedeTenerNulo ?? 'Por defecto';  // Si vale null, devuelve la cadena 'Por defecto' y sino la cadena
  print (cadena);
  varPuedeTenerNulo = 'Nueva Cadena';
  cadena = varPuedeTenerNulo ?? 'Por defecto'; 
  print (cadena);
  
}



Listas

  • Conjunto de datos que tienen todos el mismo tipo (fijarse que si la definimos como de tipo dynamic, podrían albergar 'tipos' diferentes).
Lo definimos con la palabra List.
Podéis:


Podríamos decir que sería equivalentes a las listas de Java.

Un ejemplo:

void main() {

  List nombres = ['Angel','Pedro','Ana'];
  print(nombres);
  
  nombres.add('Luisa');
  print(nombres);
  
  nombres.removeAt(1);
  nombres.remove('Ana');
  print(nombres);
  
}
Flutter dart tipo datos 11.JPG


  • Nota Importante: Fijarse que al no indicar el tipo de dato de cada uno de los elementos de la lista, DART la define como de tipo <dynamic>
Flutter dart tipo datos 12.JPG
Por lo tanto, al código anterior podríamos añadir cualquier dato de cualquier tipo, ya que todos son dynamic.
Es mejor indicar el tipo de dato que va a guardar la lista:
void main() {

  List<String> nombres = ['Angel','Pedro','Ana'];
  // var nombres = <String>['Angel','Pedro','Ana'];  // Otra forma de definir una lista de Strings

  print(nombres);
  
}



Recorriendo listas

  • Veremos posteriormente con las funciones otras formas más rápidas de recorrer listas.
Por ahora, veamos la forma 'tradicional' empleando un contador desde la posición 0 hasta el número de elementos de la lista.
void main() {

  List<String> nombres = ['Angel','Pedro','Ana'];
  print(nombres);
  
  nombres.add('Luisa');
  
  for(var i=0; i<nombres.length;i++){
    print('Posición $i => valor ${nombres[i]}');
  }
  
}
Fijarse como para poder emplear nombres[i] dentro de la cadena, debemos de emplear { }. Si no lo hiciéramos, sólo podríamos acceder a 'nombres', es decir, a todo la lista completa.


void main() {

  List<String> nombres = ['Angel','Pedro','Ana'];
    
  var iter = nombres.iterator;
  while(iter.moveNext()){
    print('El elemento de la lista: ${iter.current}');
  }

}


  • Aunque lo más normal es emplear la forma for...in:
void main() {

  List<String> nombres = ['Angel','Pedro','Ana'];
    
  
  for(String valor in nombres){
    print('El elemento de la lista $valor');
  }

}


  • Nota: Veremos más adelante que existe otra forma, empleando el método forEach() que lleva como argumento una función a la cual va a llamar por cada elemento de la lista.



Mapas

  • A diferencia de las listas, este tipo de almacenamiento permite guardar un valor 'clave' y asociar dicha entrada a un valor 'asociado'.
Sería el equivalente a los mapas de Java.
  • Consultar en este enlace todos las propiedades y métodos de la clase Map.
  • Al igual que todo lo demás, podríamos definirlo como var, final o const, pero digamos que la palabra reservada para definirla es: Map
Veamos un ejemplo:
void main() {

  Map<String,dynamic> ordenador = {
    'marca' : 'HP',
    'hd' : 2000,
    'cpu' : '4ghz',
    'nucleos' : 8,
    'ssd' : true
  };
  
  print(ordenador);
}

Nota: Fijarse que en la definición del Mapa establecemos el tipo de dato:

  • De la clave
  • Del dato asociado a la clave.
En el ejemplo, la clave siempre tiene un valor 'cadena' mientras que los datos asociados a esas claves varían (String, boolean, numérico) por eso lo definimos como dynamic. Podríamos tener también la clave como dynamic si tivéramos como clave valores de cualquier tipo, como boolean, numérico,....
Si queremos acceder al valor de una clave cualquiera, lo haremos de una forma parecida a las listas (pero no confindirse, en las listas ponemos la posición mientras que en los mapas ponemos el valor de la clave
void main() {

  Map<String,dynamic> ordenador = {
    'marca' : 'HP',
    'hd' : 2000,
    'cpu' : '4ghz',
    'nucleos' : 8,
    'ssd' : true
  };
  
  print("El ordenador ${ordenador['marca']} con un disco de ${ordenador['hd']} GB funciona a una velocidad de ${ordenador['cpu']} teniendo ${ordenador['nucleos']} núclos. ");
  ordenador['ssd'] == true ? print ('SSD:SI') : print ('SSD:NO');
}
Fijarse que para acceder a un elemento concreto dentro de una cadena tenemos que encerrar la expresión entre { } como ya hicimos antes con las listas.
  • Veamos un ejemplo en el que añadimos y quitamos elementos al mapa:
void main() {

  Map<String,dynamic> ordenador = {
    'marca' : 'HP',
    'hd' : 2000,
    'cpu' : '4ghz',
    'nucleos' : 8,
    'ssd' : true
  };
  
  ordenador.remove('hd'); // Elimima una entrada
  print(ordenador);
  ordenador.addAll({'precio' : 1000.34, 'oferta' : '10%'}); // Añadimos dos entradas
  print(ordenador);
}
Nota: Otra forma de añadir nuevos elementos es simplemente asignar a la nueva clave un nuevo valor de la forma: ordenador['stock'] = 10;


  • En DART existen otros tipos de mapas al visto en estos ejemplos.
Podéis consultar los diferentes tipos en: https://api.dart.dev/stable/2.13.4/dart-core/Map-class.html



Recorriendo mapas

  • Veremos con las funciones otras formas de recorrer un mapa.
Por lo de ahora vamos a ver dos formas:
  • En una no necesitamos acceder a las claves, sólamente a los valores.
  • En otra accedemos a las claves y los valores del mapa.
  • Accediendo sólo a los valores:
void main() {

  Map<String,dynamic> ordenador = {
    'marca' : 'HP',
    'hd' : 2000,
    'cpu' : '4ghz',
    'nucleos' : 8,
    'ssd' : true
  };
  
  for(dynamic valor in ordenador.values){
    print("Valor obtenido:$valor");
  }
}
Fijarse que debemos de poner en valor el tipo de dato con el que esté definido el map para los valores.
  • Accediendo a las claves y los valores:
void main() {

  Map<String,dynamic> ordenador = {
    'marca' : 'HP',
    'hd' : 2000,
    'cpu' : '4ghz',
    'nucleos' : 8,
    'ssd' : true
  };
  
  for(MapEntry<String,dynamic>mpentry in ordenador.entries){
    print("Clave obtenida: ${mpentry.key} Valor obtenido:${mpentry.value}");
  }
}
En este caso creamos una variable de tipo MapEntry que representa cada una de las entradas del mapa. Cada entrada del mapa lo forma un par de clave-valor de tipo <String,dynamic> que es como está definido en el mapa y por eso mpentry tiene que ser de ese tipo.
Posteriormente dentro del bucle podemos acceder a las propiedades:
  • key: Para acceder a la clave.
  • value: Para acceder al valor asociado a esa clave.



Valores nulos al utilizar mapas

  • Cuando definimos un mapa y queremos recuperar el valor de una clave, si no usamos como tipo de dato de los valores 'dynamic' tendremos un problema.
Veamos cual.
Imaginemos que en el ejemplo anterior definimos el mapa de tipo <String, String>
void main() {

  Map<String,String> ordenador = {
    'marca' : 'HP',
    'hd' : '2000',
    'cpu' : '4ghz',
    'nucleos' : '8',
    'ssd' : '1'
  };
  
}
Si ahora intentamos asignar el valor a una variable nos dará el siguiente error:
Flutter dart mapas 1.JPG
Lo que está indicando es que no se puede asignar algo que puede devolver null a una variable que no acepta valores nulos.
void main() {

  Map<String,String> ordenador = {
    'marca' : 'HP',
    'hd' : '2000',
    'cpu' : '4ghz',
    'nucleos' : '8',
    'ssd' : '1'
  };
  
  String valor = ordenador['marca'];
}


Para resolver este problema tenemos 3 posibles soluciones:

  • Definir la variable como que acepta valores nulos:
  
  String? valor = ordenador['marca'];
  print(valor);
  • Indicar a DART que tiene que devolver en caso de que el valor para esa clave del mapa sea nulo. Para eso empleamos el operador ??:
  
  String valor = ordenador['nada'] ?? 'Opel';
  print(valor);
  • Indicarle a DART que puede confiar en nosotros y que sabemos que el valor a asignar nunca va a ser null. Para ello empleamos el operador ! de la forma:
  String valor = ordenador['marca']!;   // LLeva ! al final
  print(valor);



Conjuntos (set)

  • Los conjuntos son un tipo de dato que guarda valores siempre del mismo tipo y no permite duplicados.
  • Las diferencias con las listas son:
  • Los conjuntos guardan los valores de forma desordenada (en las listas aparecen en el orden en que son añadidos).
  • No permite guardar valores duplicados.
  • No se permite acceder al elemento del conjunto empleando un índice como sucede en las listas.


  • La forma de definir un conjunto es:
var setName = <type>{};  // CUIDADO, ya que si no indicamos el tipo de datos, será definido como un mapa de literales.
var setName = {'valor1','valor2',....}; // Aquí no definimos el tipo, pero al dar unos valores iniciales Dart ya sabe que es un conjunto de String´s
Set<type> setName = {};
Veamos algunas operaciones básicas:
void main() {

  var conjunto = {'Angel','Luis','Ana','María'};
  
  print(conjunto);
  conjunto.add('Pedro'); // Añade un elemento
  conjunto.remove('Angel'); // Borra un elemento
  
  print(conjunto);
  print(conjunto.elementAt(0)); // Elemento de la posición 0
  
  conjunto.clear(); // Borra todos los elementos
     
}
  • En DART existen otros tipos de conjuntos del visto en estos ejemplos.
Podéis consultar los diferentes tipos en: https://api.dart.dev/stable/2.13.4/dart-core/Set-class.html



Recorriendo conjuntos

  • De una forma parecida a las listas:
void main() {

  var conjunto = {'Angel','Luis','Ana','María'};
  
  print(conjunto);
  conjunto.add('Pedro'); // Añade un elemento
  conjunto.remove('Angel'); // Borra un elemento
  
  for(int i=0; i<conjunto.length;i++){
    print('Elemento del conjuinto: ${conjunto.elementAt(i)}');
  }
}


void main() {

  var conjunto = {'Angel','Luis','Ana','María'};
  
  var iter = conjunto.iterator;
  while(iter.moveNext()){
    print('El elemento del conjunto: ${iter.current}');
  }

}


Veremos con las funciones otras formas de recorrer los conjuntos.



Enum

  • Son un tipo especial de clase utilizada para representar un número fijo de valores constantes.
La definición es: enum Valores { valor1, valor2, valor...};
A cada valor del tipo enum se le asigna número empezando por el 0, pudiendo acceder a dichos valores de la forma Valores.values[posición]
Veamos un ejemplo:
enum Estado { 
   parado, 
   corriendo, 
   pausado, 
} 

void main(){
  
  
  Estado estado = Estado.parado;
  
  print('El estado actual es $estado');
  print('El valor de la posición 1 del tipo enum Estado es ${Estado.values[1]}');
  Estado.values.forEach((estado) => print('Estado $estado'));
}




Ejercicios propuestos

  • Ejercicio 1: En un mismo programa ejecuta las siguientes órdenes.
Define una variable de nombre valorMedio que tenga de valor 12.2321 y haz que sólo se muestre 1 decimal.
Asigna a la variable anterior el valor 'Juan' y añade dentro de una orden print, el valor Fernández.



  • Ejercicio 2: En un mismo programa ejecuta las siguientes órdenes.
Define una variable entera de nombre var1 con valor inicial 0.
Define una constanta de nombre numeros, con valor 10.
Suma a la variable var1, los números indicados en al constante numeros. Por ejemplo, si numeros vale 5, debemos sumar a var1: 1+2+3+4+5.
Asigna a la variable media el resultado de dividir la suma anterior entre numeros. Dicha variable debe guardar sólo 2 dígitos decimales.
Muestra empleado la orden print (haz todo lo necesario dentro de dicha orden) la siguiente frase: La suma de los XX primeros números da YY y la media es de ZZ.CC.



  • Ejercicio 3: En un mismo programa ejecuta las siguientes órdenes.
Define una función de nombre concatenar, que dados 3 datos (no sabes los tipos) devuelva una cadena con la concatenación de los 3 valores recibidos, separados por guiones.
Define tres constantes con los siguientes valores: 'CASA', 'COMPRADA', Fecha_Actual (aparecerá también la hora y en formato inglés)
Muestra empleando la orden print, el resultado de llamar a la función anterior.
Define una variable de nombre cadena y valor inicial 'VENDIDA'.
Guarda en una constante el resultado de llamar a la función enviando como datos 'CASA', VENDIDA', Fecha_Actual
Muestra el valor de la constante anterior.
Muestra empleando la orden print, el resultado de llamar a la función anterior con los siguientes datos: 'MANSION','PRECIO',12543.45. (cuidado con las comillas, también puedes emplear las doble comillas dentro de print :) )


Nota: Dart-Flutter tienen muchos 'paquetes' que permiten aumentar las funcionalidades. Si te atreves, busca en https://pub.dev/ el paquete intl y emplea la función DateFormat para dar el formato español a la fecha. Para instalarlo necesitas 'parar' la ejecución y volver a ejecutar el programa una vez modifiques el archivo pubspec.yaml.



  • Ejercicio 4: En un mismo programa ejecuta las siguientes órdenes.
Crea una función de nombre getNumCaracteres que reciba una cadena y devuelva la misma cadena sin espacios en blanco en el lado izquierdo. En caso de que la cadena sea null deberá devolve null. No emplees ninguna condición if dentro del código.
Llama a la función con varios valores incluído el valor null dentro de la orden print, definiendo los valores en una variable.



  • Ejercicio 5: En un mismo programa ejecuta las siguientes órdenes.
Crea una función de nombre cambiar que reciba dos parámetros de tipo cadena. El primero puede aceptar valores nulos.
La función debe devolver el primer parámetro si no vale nulo. En caso contrario debe devolver el segundo.
Llama a la función con varios valores incluído el valor null dentro de la orden print, definiendo los valores en una variable.




Soluciones ejercicios propuestos

  • Ejercicio 1: En un mismo programa ejecuta las siguientes órdenes.
Define una variable de nombre valor_medio que tenga de valor 12.2321 y haz que sólo se muestre 1 decimal (haz todo lo necesario dentro de la orden print).
Asigna a la variable anterior el valor 'Juan' y añade dentro de una orden print, el valor Fernández.
void main() {
  
  dynamic valorMedio = 12.2321;
  
  print('${valorMedio.toStringAsFixed(1)}');
  
  valorMedio = 'Juan';
  print('$valorMedio Fernández');

}



  • Ejercicio 2: En un mismo programa ejecuta las siguientes órdenes.
Define una variable entera de nombre var1 con valor inicial 0.
Define una constanta de nombre numeros, con valor 10.
Suma a la variable var1, los números indicados en al constante numeros. Por ejemplo, si numeros vale 5, debemos sumar a var1: 1+2+3+4+5.
Asigna a la variable media el resultado de dividir la suma anterior entre numeros. Dicha variable debe guardar sólo 2 dígitos decimales.
Muestra empleado la orden print (haz todo lo necesario dentro de dicha orden) la siguiente frase: La suma de los XX primeros números da YY y la media es de ZZ.CC.
void main() {
  

  const numeros = 10;   // Mejor const ya que se guarda en compilación
  int var1=0;
  for(int cont=1; cont < numeros; cont++){
    var1 += cont;
  }
  double media = double.parse((var1/numeros).toStringAsFixed(2));
  
  print('La suma de los $numeros primeros números es de $var1 y la media es de $media');
  
  
}




  • Ejercicio 3: En un mismo programa ejecuta las siguientes órdenes.
Define una función de nombre concatenar, que dados 3 datos (no sabes los tipos) devuelva una cadena con la concatenación de los 3 valores recibidos, separados por guiones.
Define tres constantes con los siguientes valores: 'CASA', 'COMPRADA', Fecha_Actual (aparecerá también la hora y en formato inglés)
Muestra empleando la orden print, el resultado de llamar a la función anterior.
Define una variable de nombre cadena y valor inicial 'VENDIDA'.
Guarda en una constante el resultado de llamar a la función enviando como datos 'CASA', VENDIDA', Fecha_Actual
Muestra el valor de la constante anterior.
Muestra empleando la orden print, el resultado de llamar a la función anterior con los siguientes datos: 'MANSION','PRECIO',12543.45. (cuidado con las comillas, también puedes emplear las doble comillas dentro de print :) )
String concatenar(Object par1, Object par2, Object par3){ // Mejor Object que dynamic ya que no vamos necesitar llamar a ningún método fuera de Object
  
  return '$par1-$par2-$par3';
  
}

void main() {
  
  const c1 = 'CASA';
  const c2 = 'COMPRADA';
  final c3 = DateTime.now();
  
  print('Resultado llamar a concatenar: ${concatenar(c1,c2,c3)}');
  
 
  String cadena = 'VENDIDA';
  final resultado = concatenar(c1,cadena,c3);
  print('Nueva llamada: $resultado'); // Debemos aconstumbrarnos a emplear las variables dentro de las comillas
  
  print('Otra llamada: ${concatenar("MANSION","PRECIO",12543.45)}');
  
  
}



  • Ejercicio 4: En un mismo programa ejecuta las siguientes órdenes.
Crea una función de nombre getNumCaracteres que reciba una cadena y devuelva la misma cadena sin espacios en blanco en el lado izquierdo. En caso de que la cadena sea null deberá devolve null. No emplees ninguna condición if dentro del código.
Llama a la función con varios valores incluído el valor null dentro de la orden print.
import 'package:flutter/material.dart';

String? getNumCaracteres(String? cad){  // Fijarse que en el caso de que cad sea null, no devuelve trimLeft(), sino null
  return cad?.trimLeft();
}

void main(){

  String? prueba;
  print("Llamando a la función ${getNumCaracteres(prueba)}");

  prueba = '   con espacios';
  print("Llamando a la función ${getNumCaracteres(prueba)}");
}



  • Ejercicio 4: En un mismo programa ejecuta las siguientes órdenes.
Crea una función de nombre getNumCaracteres que reciba una cadena y devuelva la misma cadena sin espacios en blanco en el lado izquierdo. En caso de que la cadena sea null deberá devolve null. No emplees ninguna condición if dentro del código.
Llama a la función con varios valores incluído el valor null dentro de la orden print.
import 'package:flutter/material.dart';

String? getNumCaracteres(String? cad){  // Fijarse que en el caso de que cad sea null, no devuelve trimLeft(), sino null
  return cad?.trimLeft();
}


void main(){

  String? prueba;
  print("Llamando a la función ${getNumCaracteres(prueba)}");

  prueba = '   con espacios';
  print("Llamando a la función ${getNumCaracteres(prueba)}");
}



  • Ejercicio 5: En un mismo programa ejecuta las siguientes órdenes.
Crea una función de nombre cambiar que reciba dos parámetros de tipo cadena. El primero puede aceptar valores nulos.
La función debe devolver el primer parámetro si no vale nulo. En caso contrario debe devolver el segundo.
Llama a la función con varios valores incluído el valor null dentro de la orden print, definiendo los valores en una variable.
import 'package:flutter/material.dart';

String cambiar(String? cad1, String cad2){ // Fijarse que el método devuelve siempre un String, por eso no pongo String?

  return cad1 ?? cad2;

}

void main(){
  String? var1;
  String var2='prueba';

  print("Llamada a la función concatenar: ${cambiar(var1,var2)}");
}



Enlace a la página principal de la UD2

Enlace a la página principal del curso




-- Ángel D. Fernández González -- (2021).