Funciones

Hasta ahora hemos visto como realizar unas cuantas tareas con nuestro código, lo cual significa que ya tenemos una razonablemente extensa batería de herramientas que podemos reutilizar en diferentes programas.

Ahora bien, cada vez que queramos hacer un corta-pega en otro programa tendremos que cambiar un montón de cosas, como definiciones de variables, valores, y a veces el orden en el que se hacen las cosas, etc. Es habitual equivocarse haciendo esto y a veces puede llevar bastante tiempo encontrar el error, aunque es más fácil que volver a escribir todo el código desde el principio.

Pero, en realidad, sería mucho más cómodo encontrar un método para sustituir todo este proceso por un simple corta pega.

Este método existe y programación se denomina encapsular el conocimiento. Hay varios métodos para realizarlo, pero hoy nos vamos a ocupar del más sencillo de ellos, la utilización de funciones.
Las funciones nos van servir para escribir código que se entiende mejor, que ahorra repeticiones innecesarias, y que permite reaprovechar gran parte del código que escribamos en otros programas.

Volver al ͍ndice

¿Qué es encapsular?

Encapsular en programación significa ocultar el estado y las operaciones internas de un determinado proceso al exterior, de forma que se pueda utilizar desde cualquier programa sin necesidad de cambiar o conocer nada de su código interno.

Es como construir una máquina que realiza su tarea siempre, independientemente de que sepamos como funcionan sus mecanismos o no, y que sólo necesita que le demos los datos necesarios para trabajar.

Pongamos un ejemplo. Hemos visto como obtener un número aleatorio dentro de un intervalo. Si quisiéramos trazar un numero aleatorio entre -5 y +5 en la consola, escribirímaos lo siguiente:

var numero:Number = Math.random() * (5 - (-5) + 1) + (-5);
trace(numero);

Y si lo escribimos simplificando las operaciones:

var numero:Number = Math.random() * 11 - 5;
trace(numero);

Supongamos que ahora queremos aprovechar este algoritmo que hemos aprendido para calcular números aleatorios en otro programa. El programa en cuestión necesita calcular un número aleatorio del 1 al 6 para simular el lanzamiento de un dado.
Si tenemos el segundo bloque de código, tendríamos que volver a pensar el cálculo y reescribirlo con cuidado:

var resultadoLanzamiento:Number = Math.random() * (6 - 1 + 1) + 1;
trace(resultadoLanzamiento);

Pero claro un dado no da números decimales. Habrá que utilizar Math.floor() para redondearlo:

var resultadoLanzamiento:Number = Math.floor(Math.random() * 6 + 1); 
trace(resultadoLanzamiento);

En esta versión también hemos simplificado la operación aritmética. Not a big deal!, pero sería mucho más cómodo tener todas estas operaciones encapsuladas, en un bloque de código que pudiéramos copiar y pegar en cualquier programa y que funcionara sin tener que hacer cámbios en él.

Encapsular con funciones

La forma más sencilla de encapsular un algoritmo (ese conjunto de operaciones del que estábamos hablando) es utilizar funciones.

Una función en programación es un bloque de código que se ejecuta sólo cuando lo llamamos, que puede recibir parámetros si lo necesita para realizar sus operaciones, y que puede devolvernos un valor para que lo utilicemos si queremos en el resto de nuestro código.

Funciones que devuelven valores, El comando return

Las funciones pueden devolver un valor, lo que es muy util cuando realizan cálculos que dan como resultado un número que necesitamos en otros lugares. Para expresar que se quiere devolver valor se utiliza el comando return delante del valor que queremos devolver.
La sintaxis de la definición de una función que devuelve un valor se esquematiza en el siguiente diagrama:
Funciones

El valor de retorno puede ser un número o cualquier otro tipo de dato, incluso un MovieClip.

Fijaos en que esta función calcula precisamente un número aleatorio dentro del intervalo que nosotros le demos en los parámetros, y que devuelve un número entero si el tercer parámetro, entero, es true.

¿Cómo usamos esta función? Asignando el resultado de llamar a la función a la variable que queremos que guarde el número aleatorio resultado de lanzar el dado:

var resultadoLanzamiento:Number = calculaNumeroAleatorio(1,6,true);
trace("El resultado de lanzar el dado ha sido:", resultadoLanzamiento);

Quizás no os parezca mucho ahorro de esfuerzo en este ejemplo, pero pensadlo bien. Si creamos funciones para cada tarea que realizamos habitualmente, sólo tenemos que pensar el código para esa tarea una sola vez, guardar la función en un lugar seguro y copiarla y pegarla cuando la necesitemos.
¡Eso es una gran ventaja! Además, evita errores y quebraderos de cabeza. Y además, hay muchas operaciones comunes que llevan mucho más código que calcular un número aleatorio,

Veamos otro ejemplo.
Acordaos del ejemplo del enjambre de instancias que se movían a destinos aleatorios constantemente. Necesitábamos primero crear las instancias de las animaciones, asignarlas al array enjambre, añadirlas a la escena y colocarlas en sus coordenadas x e y. Lo hacíamos con el siguiente bucle:

const NUM_ABEJAS:int = 30;
const ANCHO_PANTALLA:int = stage.stageWidth;
const ALTO_PANTALLA:int = stage.stageHeight;
// Este es el bucle que rellena el array y coloca las instancias en la escena
for (var i:int = 0 ; i < NUM_ABEJAS ; i++ ) 
{
	// rellenamos el elemento i del array con una nueva instancia de la animación
	enjambre[i] = new AnimCirculo();
	// Fijamos aleatoriamente las coordenadas de la nueva instancia
	enjambre[i].x = Math.random() * ANCHO_PANTALLA;
	enjambre[i].y = Math.random() * ALTO_PANTALLA;
	// Y la añadimos a la lista de visualización de la escena.
	addChild(enjambre[i]);
}

Las instrucciones que están en las líneas reasaltadas las hemos utilizado un montón de veces desde entonces y las vamos a utilizar todavía más. Por eso conviene encapsularlas en una función que, siempre que queramos hacer lo mismo, no tengamos que tocar más.

function colocarInstanciaEnEscena(Clase:Class, posicionX:Number, posicionY:Number):MovieClip {
	var instancia:MovieClip = new Clase();
	instancia.x = posicionX;
	instancia.y = posicionY;
	addChild(instancia);
	return instancia;
}

Antes de ver como se utilizaría, fijémonos en los detalles. A la función le tendremos que pasar tres parámetros para que funcione correctamente. El primero, Clase, es la clase de AS3 a la que asociamos el símbolo que exportamos para AS3 (el nómbre que le ponemos en el campo Clase del diálogo de propiedades del símbolo).
exportar para actionScript
Este parámetro es una variable de tipo Class.

El segundo y tercer parámetros son dos números que se utilizarán para colocar la instancia creada en su poseción x e y en la escena.

Y por último, vemos que devuelve un valor de tipo MovieClip, ¿por qué? ¿para qué? Pues para que cuando llamamos a la función podamos asignar la instancia que hemos creado a una variable o un elemento de un array, de forma que tengamos un nombre por el que llamarla cuando la queramos recolocar en la escena, cambiar su tamaño, o cualquier otra de las operaciones que se pueden realizar con un MovieClip.

Así, el código que creaba el enjambre de instancias quedaría:

function colocarInstanciaEnEscena(Clase:Class, posicionX:Number, posicionY:Number):MovieClip {
	var instancia:MovieClip = new Clase();
	instancia.x = posicionX;
	instancia.y = posicionY;
	addChild(instancia);
	return instancia;
}

for (var i:int = 0 ; i < NUM_ABEJAS ; i++ ) 
{
	// La siguiente línea está dividida en tres partes, para que quepa bien en pantalla
	// no es obligatorio escribirla así, normalmente se hará en una sola línea.
	enjambre[i] = colocarInstanciaEnEscena( AnimCirculo,  
											Math.random() * ANCHO_PANTALLA, 
											Math.random() * ALTO_PANTALLA) ;
}

No es que hayamos escrito mucho menos, pero si ya hubiéramos tenido precocinada y guardada la función colocarInstanciaEnEscena(), esa parte sólo habríamos tenido que pegar.
De hecho, a partir de ahora, cada vez que queramos realizar el conjunto de operaciones que crean, colocan y añaden una instancia en escena, solo tendremos que pegar esa función en nuestro código.

Funciones que no devuelven valores, El tipo de datos void

Hay veces que no interesa que nuestra función devuelva un parámetro, porque realiza una serie de tareas sobre objetos de los que ya tenemos una referencia (un nombre por el que llamarlos) o porque no necesitamos hacer nada más sobre esos objetos.

Como ejemplo podemos crear una función que escala una instancia de MovieClip sin cambiar la relación de aspecto.
FuncionesVoid
En este caso no necesitamos devolver ningín valor, sólo hacemos una operación sobre la instancia que le pasamos a la función. Por eso ni ponemos una sentencia con el comando return ni utilizamos como tipo de dato de retorno un tipo “normal”, en su lugar utilizamos el tipo de datos “vacío”, void.

Ejercicios

  1. Escribir una función que sume 2 números. Para comprobar que funciona utiliza el siguiente método:
    	var num1:Number = 10;
    	var num2:Number = -7;
    	var miSuma:Number = suma(num1, num2); // por ejemplo.
    	trace("La suma de", num1, "y", num2, "da", miSuma);
    	

    En la consola debería aparecerte:
    La suma de 10 y -7 da 3

  2. Escribir una función que multiplique dos números y devuelva el resultado. Combrueba que funciona.
  3. Escribir una función que reciba como parámetros un MovieClip, y unos valores mínimo y máximo para su escala. La función debe escalar de forma aleatoria el MovieClip recibido, entre los valores recibidos, preservando la relación de aspecto
  4. Escribir una función que reciba como parámetros un MovieClip, y unas coordenadas x e y mínimas y máximas.
    La función debe colocar el MovieClip recibido entre las coordenadas recibidas de forma aleatoria.
  5. Utiliza la función colocarInstanciaEnEscena junto con un bucle para colocar 8 estrellas girando sobre sí mismas, en las posiciones que quieras de la pantalla
  6. Crea un símbolo de forma que en cada fotograma contenga la cara correspondiente al número del fotograma de un dado.
    Exportalo para actionscript.
    Después haz un programa que añada cuatro instancias del dado a la escena y que haga tiradas de 4 dados utilizando las funciones que hemos visto.
  7. Trata de optimizar el programa anterior de forma que tengas que repetir la menor cantidad de instrucciones, modificando las funciones que hemos visto según creas necesario.
  8. Escribir una funcion que calcule la distancia entre dos puntos. La función debe recibir las cordenadas x e y de los dos puntos para funcionar. (Ver Distancia entre dos puntos))
  9. Escribir una funcion que calcule la distancia entre dos instancias de MovieClip. La función debe recibir las dos instancias como parámetros.

Volver al ͍ndice

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *