Fundamentos de Dart: Tu Primera Inmersión en la Programación

Elementos Fundamentales del Lenguaje Dart

¿Qué es Dart?

Dart es un lenguaje de programación orientado a objetos desarrollado por Google. Aunque no está técnicamente restringido, se utiliza principalmente para crear interfaces de usuario frontend para la web (con AngularDart o Flutter for Web) y aplicaciones móviles (Flutter). Está en desarrollo activo, compilado a código de máquina nativo (cuando se utiliza para construir aplicaciones móviles), inspirado en características modernas de otros lenguajes de programación (principalmente Java, JavaScript, C#) y es fuertemente tipado.

Como ya se mencionó, Dart es un lenguaje compilado. Esto significa que tu código no se ejecuta como lo escribes, sino que un compilador lo analiza y transforma (a código de máquina).

¿Qué son los “Tipos”?

No todos los lenguajes de programación son fuertemente tipados, pero Dart sí lo es. ¿Qué significa eso? Cada valor que utilizas en tu programa (por ejemplo, la entrada de usuario que estás guardando) tiene un tipo; podría ser “texto”, por ejemplo. En Dart (y en prácticamente todos los demás lenguajes de programación), eso no se llamaría “texto”, sino “cadena” o “string”. Por otro lado, si estás trabajando con la edad de un usuario, podrías estar utilizando un número sin decimales, un valor llamado “entero” o “integer”. Los números con decimales se llaman “dobles” (o “float” en otros lenguajes de programación). Estos son algunos tipos básicos; sin embargo, Dart tiene muchos más que estos. Aprenderás más sobre estos (y todos los demás tipos importantes) a lo largo del curso. En este momento, estos son los tipos que debes tener en cuenta: Es importante tener en cuenta que CADA valor en Dart es un objeto. Más sobre eso se puede encontrar a continuación (=> “¿Qué significa ‘Orientado a Objetos’?”).

Variables y Funciones

En tus programas, generalmente necesitas almacenar algunos valores, no necesariamente en una base de datos o en un archivo, sino en la memoria. Puede que necesites almacenar algún resultado intermedio, la entrada de un usuario antes de procesarla o alguna información sobre tu widget de Flutter (por ejemplo, “¿Debería mostrarse actualmente en la pantalla?”).

Almacenas esa información (es decir, valores) en variables. Las variables son contenedores de datos: tienen nombres y almacenan valores de cualquier tipo. Por ejemplo:

var miEdad = 30;

es una variable que almacena un entero (int) de valor 30. La palabra clave var le dice a Dart que miEdad es una variable. Alternativamente a var, también podrías usar el nombre del tipo; además de informarle a Dart sobre la variable, también “informarías a Dart” sobre el tipo de datos almacenado en la variable:

int miEdad = 30;

Sin embargo, Dart tiene una característica llamada “inferencia de tipos”. Esto significa que Dart es bastante inteligente para inferir tipos de valores. Si creaste la variable con var, Dart aún puede inferir que miEdad es de tipo int porque inicializas la variable (es decir, le asignas un valor desde el principio) con un valor entero.

Debido a esa inferencia de tipos incorporada, se considera una buena práctica NO definir explícitamente el tipo, sino usar var al definir variables. Por lo tanto, este fragmento sería preferido:

var miEdad = 30;

Eso cambia si creas una variable sin un valor inicial; en ese caso, deberías informar a Dart sobre qué tipo de datos planeas almacenar en ella:

int miEdad;
miEdad = 30;

Además de las variables, otra característica fundamental de CUALQUIER lenguaje de programación son las “funciones”. Las funciones te permiten “externalizar” código en “fragmentos de código reutilizables”. Aquí tienes un ejemplo:

var precio1 = 9.99;
var precio2 = 10.99;
var total = precio1 + precio2;
var numDeRondas1 = 10;
var numDeRondas2 = 45;
var totalRondas = numDeRondas1 + numDeRondas2;

En este ejemplo, tenemos la misma lógica de sumar dos números en dos lugares diferentes de nuestro código. En lugar de repetirnos, sería genial poner esa lógica en una función que podamos llamar tantas veces como queramos. Aquí está el fragmento modificado, usando una función:

num sumarNumeros(num n1, num n2) {
// usa 'num' como tipo porque debería funcionar con int y double
return n1 + n2;
}
var precio1 = 9.99;
var precio2 = 10.99;
var total = sumarNumeros(precio1, precio2);
var numDeRondas1 = 10;
var numDeRondas2 = 45;
var totalRondas = sumarNumeros(numDeRondas1, numDeRondas2);

Por supuesto, a primera vista, este código ahora es más largo y complejo. Pero la ventaja es que, si alguna vez necesitas cambiar tu lógica de adición, lo haces en un solo lugar, dentro de la función. No tienes que editar múltiples lugares en el código solo para cambiar el + por un – por ejemplo (si quisieras hacer eso). Las funciones pueden tomar argumentos (los datos entre los paréntesis) que son básicamente variables, con alcance limitado a la función. “Alcance” significa que solo puedes usar las variables dentro de la declaración de bloque (= cuerpo de la función, el código entre las llaves {}) donde las definiste. Además, las funciones también pueden devolver valores, como el resultado de la adición en este ejemplo.”

¿Qué significa “Orientado a Objetos”?

Dart es un lenguaje de programación orientado a objetos, lo que significa que cada valor en Dart es un objeto, incluso un número simple.

¿Pero qué son los “objetos”?

Los objetos son estructuras de datos que encuentras en muchos lenguajes de programación. En Dart, cada valor es un objeto, incluso valores primitivos como texto (String) o números (enteros y decimales). Pero también tienes objetos integrados más complejos (por ejemplo, listas de datos) y puedes construir tus propios objetos.

A menudo construyes tus propios objetos si deseas expresar relaciones más complejas entre datos o si deseas encapsular cierta funcionalidad en “un bloque de construcción”.

Los objetos se crean con la ayuda de “Clases” porque cada objeto necesita un plano (la clase) en base al cual puedes luego crearlo (“instanciarlo”).

Aquí tienes un ejemplo de definición de clase:

class Persona { 
var nombre = 'Max'; 
var edad = 30; 
void saludar() { 
print('Hola, soy ' + nombre + ' y tengo ' + edad.toString() + ' años.'); 
} 
}

En este ejemplo, definimos una clase Persona que tiene dos variables a nivel de clase (también llamadas “campos de instancia” o “propiedades”) y una función a nivel de clase (también llamada “método”).

Como puedes ver, también utilizamos tipos en las clases, tanto para propiedades (variables) como para métodos (funciones).

También puedes observar que dentro del método saludar, podemos acceder a las propiedades de la clase, nombre y edad, sin problemas (edad.toString() se utiliza para convertir el valor entero a una cadena al mostrarlo en una cadena más larga).

¡Sin embargo, la clase solo sirve como un plano! Por sí sola, ¡no te da un objeto! En cambio, ahora puedes crear objetos basados en esta clase:

void main() { 
var yo = Persona(); 
print(yo.nombre); // utiliza el punto para acceder a propiedades y métodos de la clase 
}

Como nota al margen: La función principal (main) es una función especial en Dart; es la función que Dart ejecutará primero cuando inicie tu aplicación.

Dentro de main, creamos un nuevo objeto basado en Persona usando Persona(). Este proceso se llama “instanciar la clase”, por lo tanto, creamos “una instancia de Persona”. El tipo de yo sería entonces Persona, ¡porque las clases siempre actúan también como tipos!”