En este curso utilizamos Flutter con el lenguaje de programación Dart, ambos desarrollados por Google.
Vamos a ver cómo hacer el Hola Mundo con Flutter, digo Dart.
Para ello vamos a ir al DartPad.
Antes de seguir quiero comentarte que este artículo es algo más que un Hola Mundo con Dart, es una pequeña introducción a este lenguaje con el que después haremos nuestras apps en Flutter. Por algo hay que empezar, iremos poco a poco.
Como vemos, tenemos un método main. Sin él no podemos trabajar, nos devuelve un error. Mejor dicho, nos devuelve tres errores. Veámoslos:
Error compiling to JavaScript:
Error: No 'main' method found.
Error: Compilation failed.
El método malin generalmente no retorna nada, por eso le ponemos delante ‘void‘.
También, una de las cosas importantes a saber ahora que estamos comenzando es que las sentencias terminan con punto y coma «;».
Así quedaría nuestro primer «Hola mundo» con Dart:
void main() {
print('Hola mundo');
}

En mi Curso de Dart gratis puedes ver más vídeos para aprender Dart. Vídeos nuevos cada semana.
Los comentarios en Dart
Los comentarios en Dart son muy fáciles:
- Comentario de una línea: usar doble barra //.
- Comentario multilínea: /* código comentado */.
Concatenación de datos con Dart
Siguiendo el ejemplo anterior, veamos la concatenación de datos con Dart.
void main() {
var nombre = 'Carlos';
print('Hola ' + nombre);
}
El resultado de esto sería «Hola Carlos». Pero también se puede hacer de otra forma. Veamos cómo podemos inyectar un String (cadena de texto) con Dart.
void main() {
var nombre = 'Carlos';
print('Hola $nombre');
}
Esto que hemos realizado es la interpolación de String.
Ahora veamos un poco los tipos de datos en Dart y comencemos a picar código y familiarizarnos con él.
Tipos de datos en Dart, Números y String
Muy simple, veamos un ejemplo de String.
String cadena;
cadena = 'Carlos';
Ejemplo de números.
// Números
int amigos;
double pi;
amigos = 12;
pi = 3.14;
Tipos de dato booleanos y condicionales ‘if-else’ en Dart
Los tipos de datos booleanos almacenan valores de verdadero o falso. Vemos cómo se dedfine un tipo de dato booleano.
void main() {
bool dato;
dato = true;
}
Y el condicional, para los que ya saben algo de programación, es muy simple. Se ejecuta el código que cumple la condición true, verdadero.
void main() {
bool encendido;
encendido = true;
if (encendido = true) {
print('Máquina encendida.');
} else {
print('Máquina apagada.');
}
}
Las listas en Dart
Una lista es una colección de objetos. Veamos algunos ejemplos de listas en Dart.
void main() {
// Lista de objetos de distinto tipo (dynamic)
List lista = ['hola', 1];
print(lista[0]);
print(lista[1]);
print('**************************');
// Lista de números enteros
List<int> listaN = [0, 23, 44];
print(listaN[0]);
print(listaN[1]);
print(listaN[2]);
}
Para añadir un elemento usamos el método add.
// Añadimos el número 77 a nuestra lista de enteros
listaN.add(77);
Veamos la creación de una lista de tamaño fijo en Dart.
// Lista de tamaño fijo
List numeros = List(5);
print(numeros);

Veamos como establecer el valor de un elemento en una lista.
List numeros = List(5);
numeros[0] = 55;
print(numeros);

Tipo de dato Map en Dart
El objeto mapa es una pareja clave/valor. Ambos pueden ser de cualquier valor. Es muy fácil el acceso a cada valor del mapa.
void main() {
Map<String, dynamic> coche = {
'marca' : 'Ford',
'modelo' : 'Focus',
'potencia' : 125,
'vendido' : false
};
print(coche['marca'] + ' ' + coche['modelo']);
print(coche['potencia']);
}

Veamos la creación de un mapa en Dart de enteros y cadenas al que añadiremos posteriormente un objeto.
// Map int/String
print('*********************************');
Map<int, String> coches = {
1: 'Alfa',
2: 'Ford',
10: 'Renault'
};
coches.addAll({3: 'Toyota'});
print(coches);
print(coches[1]);
print(coches[2]);
print(coches[10]);
print(coches[3]);
El resultado sería el siguiente:
Veamos las Funciones en Dart
Veamos un sencillo repaso a las funciones.
void main() {
decirHola();
}
void decirHola() {
print('Hola');
}

Veamos cómo pasamos parámetros a las funciones y cómo podemos nombrar a los parámetros en Dart.
void main() {
decirHola();
retornarCadena();
print(retornarCadena());
String resultado = retornarTexto(saludo: 'Hola,', nombre: 'Juan');
print(resultado);
}
void decirHola() {
print('Hola');
}
String retornarCadena() {
return 'Hola desde la función';
}
// Función cuyos parámetros tienen nombre
retornarTexto({ String saludo, String nombre }) {
return '$saludo $nombre';
}
Por último, quiero enseñaros cómo en este lenguaje también podemos usar las funciones de flecha.
void main() {
String resultado = retornarTextoFlecha(saludo: 'Hola,', nombre: 'Juan');
print(resultado);
}
// Función cuyos parámetros tienen nombre
retornarTexto({ String saludo, String nombre }) {
return '$saludo $nombre';
}
// Función de flecha
retornarTextoFlecha({ String saludo, String nombre }) => '$saludo $nombre';

Clases en Dart
Para definir una nueva instancia de una clase en Dart, el new es opcional.
void main() {
var miCoche = new Coche();
var miCoche2 = Coche();
}
class Coche {
String marca;
String modelo;
}
Las clases en Dart tienen propiedades y métodos. Para distinguir entre métodos y funciones diremos que los métodos se encuentran dentro de una clase y las funciones fuera.
La clase Coche tiene como propiedades «marca» y «modelo». Si usamos final estamos indicando que ese objeto no va cambiar su valor nunca.
void main() {
var miCoche = new Coche();
var miCoche2 = Coche();
final miCoche3 = Coche();
}
class Coche {
String marca;
String modelo;
}
Veamos el Constructor de una Clase con argumentos posicionales.
void main() {
final miCoche3 = Coche('Renault', 'Clio');
print(miCoche3.marca);
print(miCoche3.modelo);
print(miCoche3);
}
class Coche {
String marca;
String modelo;
// Constructor con argumentos posicionales
Coche(String marca, String modelo) {
this.marca = marca;
this.modelo = modelo;
}
// Sobreescribimos el método toString
String toString() {
return '${ this.marca } - ${ this.modelo }';
}
}
Si queremos mantener el orden de los argumentos usamos el constructor con named arguments (argumentos con nombre). Veamos como quedaría el ejemplo anterior.
void main() {
final miCoche3 = Coche(marca: 'Renault', modelo: 'Clio');
print(miCoche3.marca);
print(miCoche3.modelo);
print(miCoche3);
}
class Coche {
String marca;
String modelo;
// Constructor con argumentos posicionales
Coche({ String marca, String modelo }) {
this.marca = marca;
this.modelo = modelo;
}
// Sobreescribimos el método toString
String toString() {
return '${ this.marca } - ${ this.modelo }';
}
}

Veamos una forma más simple, más corta, que tenemos de escribir el constructor.
void main() {
final miCoche3 = Coche(marca: 'Renault', modelo: 'Clio');
print(miCoche3.marca);
print(miCoche3.modelo);
print(miCoche3);
}
class Coche {
String marca;
String modelo;
// Constructor con argumentos posicionales
/*Coche({String marca, String modelo}) {
this.marca = marca;
this.modelo = modelo;
}*/
// Constructor más simple (con argumentos posicionales en este caso)
Coche({ this.marca, this.modelo });
// Sobreescribimos el método toString
String toString() {
return '${this.marca} - ${this.modelo}';
}
}
Constructores con nombre en Dart
Veamos un ejemplo de los constructores con nombre en Dart. Para esto, vamos a importar dart:convert.
import 'dart:convert';
void main() {
// final miCoche = Coche('Renault', 'Clio');
final rawJson = '{"marca": "Renault", "modelo": "Clio"}';
Map parsedJson = json.decode(rawJson);
print(parsedJson);
// Uso del constructor con nombre creado abajo
final coche2 = new Coche.fromJson( parsedJson );
print(coche2.marca);
print(coche2.modelo);
}
class Coche {
String marca;
String modelo;
Coche( this.marca, this.modelo );
Coche.fromJson( Map parsedJson ) {
marca = parsedJson['marca'];
modelo = parsedJson['modelo'];
}
}
Los getters y setters en Dart
Vamos a ver los getters y setters en Dart y ya verás cómo no hay tanta complicación en la cosa. Veamos algún ejemplo. Debéis aprender que al ponerun «_» delante de cualquier propiedad, se hace privada. Sólo es visible dentro de esa clase.
void main() {
final cuadrado = Cuadrado();
cuadrado.lado = 2;
print(cuadrado);
print('Área: ${cuadrado.area}');
}
class Cuadrado {
double _lado;
// double _area;
set lado( double valor ) {
// Lanzamos un error si es menor o igual que 0
if ( valor <= 0) {
throw('El valor debe ser mayor que 0.');
}
// Si el valor es positivo se lo damos al lado.
_lado = valor;
}
// Calculamos el área del cuadrado
/*double get area {
return _lado * _lado;
}*/
// Método simplificado
double get area => _lado * _lado;
toString () => 'Lado: $_lado';
}
Clases abstractas en Dart
En Dart, las clases abstractas se designan con la palabra reservada abstract class.
Para indicar que se implementa una clase, en Dart usamos la palabra reservada implements.
En Dart, las clases abstractas no pueden ser creadas con el constructor new. Una clase abstracta obliga a otras clases a que implementen sus propiedades y métodos. Veamos un ejemplo donde dos clases que son modelos de coche tienen que heredar obligatoriamente el atributo y el método que tiene la clase abstracta Coche.
void main() {
final clio = new Clio();
final focus = Focus();
clio.pitar();
focus.pitar();
}
// final clio = new Coche();
abstract class Coche {
int ruedas;
void pitar() {
print('piiiiiiiiiiiii');
}
}
// Clio implementa la clase abstracta Coche
class Clio implements Coche {
int ruedas;
int ventanillas;
String matricula;
void pitar() => print('piiii');
}
// Focus implementa la clase abstracta Coche
class Focus implements Coche {
int ruedas;
void pitar() => print('peee');
}
Si no se emplementan el atributo y el método, da error. El resultado sería el siguiente.

Extends en Dart
Cuando una clase extiende de otra, va a tener todas sus propiedades y métodos. Lo entenderéis claramente viendo el siguiente ejemplo de extends en Dart.
void main() {
final coche = Coche();
coche.marca = 'Renault';
final camion = Camion();
camion.marca = 'Volvo';
}
// Añadimos abstract para que no se puedan crear instancias de Vehiculo
abstract class Vehiculo {
String marca;
String modelo;
}
// La clase Coche extiende de Vahiculo
class Coche extends Vehiculo {
int lMaletero;
}
// La clase Camion extiende de Vahiculo
class Camion extends Vehiculo {
int lRemolque;
}
Mixins en Dart
En Dart, los Mixins es una forma de sólo asignar a las clases lo que necesitamos.
Usamos la palabra reservada with para hacer el mixin. Veamos un ejemplo muy demostrativo y claro con clases de animales, que vienen de hacer mixin de varias clases.
abstract class Animal {}
// Clases principales
abstract class Mamifero extends Animal {}
abstract class Ave extends Animal {}
abstract class Pez extends Animal {}
// Clases Mixins
abstract class Volador {
void volar() => print('Estoy volando');
}
abstract class Caminante {
void caminar() => print('Estoy caminando');
}
abstract class Nadador {
void nadar() => print('Estoy nadando');
}
// Creamos los animales
class Delfin extends Mamifero with Nadador {}
class Murcielago extends Mamifero with Volador {}
class Gato extends Mamifero with Caminante {}
class Paloma extends Ave with Caminante, Volador {}
class Pato extends Ave with Caminante, Volador, Nadador {}
class Tiburon extends Pez with Nadador {}
class PezVolador extends Pez with Nadador, Volador {}
// Clase main
void main(){
final pato = Pato();
pato.volar();
final pezVolador = PezVolador();
pezVolador.nadar();
pezVolador.volar();
}

Futures en Dart
Son muy importantes cuando estamos haciendo tareas asíncronas. Un Future es una tarea asíncrona que se hace en un hilo independiente del hilo principal que estamos ejecutando y cuando se resuelve nosotros podemos seguir ejecutando otras partes de nuestro programa.
Los Futures pueden dar errores. Usamos la palabra reservada Future. Veamos un ejemplo con código, donde nuestro Future va a tardar 4 segundos más que el hilo principal.
void main() {
print('Vamos a pedir datos.');
httpGet('http://api.dominio.com/ejemplo').then((data) {
print( data );
});
print('Línea final');
}
Future<String> httpGet(String url) {
return Future.delayed( new Duration(seconds: 4), () {
return 'Hola, ¿qué tal?';
} );
}
¿Qué es Async – Await? ¿Para que sirve?
El Async nos ayuda a transformar una función en una tarea asíncrona y Await nos permite esperar a que se resuelva dicha tarea, aunque nos de error.
Para poder usar el await, debemos estar a la fuerza dentro de una función async.
Los constructores en una clase no pueden ser asíncronos. No, no se pueden hacer constructores asíncronos.
Vamos a verlo transformando todo el ejemplo anterior, vamos a esperar a que la tarea se ejecute y luego pasaremos a la impresión de la última línea.
void main() async {
print('Vamos a pedir datos.');
String data = await httpGet('http://api.dominio.com/ejemplo');
print( data );
print('Línea final');
}
Future<String> httpGet(String url) {
return Future.delayed( new Duration(seconds: 4), () {
return 'Hola, ¿qué tal?';
} );
}
Ahora puedes seguir este Curso de Flutter con la instalación de Flutter en Windows.
Gracias por la información me sirvió de mucha ayuda para una investigación para mi tarea de programación sobre Dart.
A ti Jessica Belen 🙂