Unidad 3. Funciones y Procedimientos
Objetivos de la Unidad
- Comprender la utilidad de las funciones como mecanismo de reutilización y modularización del código.
- Distinguir entre funciones (con valor de retorno) y procedimientos (
void). - Aplicar el concepto de ámbito de variables (scope) y paso de parámetros por valor y por referencia.
- Implementar programas modulares usando composición de funciones y funciones auxiliares (helpers).
- Seguir buenas prácticas de nomenclatura, cohesión y documentación Javadoc.
1. ¿Por qué necesitamos Funciones?
Imagina que estás construyendo un programa complejo. Al principio, todo tu código está en el método main. Pero pronto, main empieza a crecer sin control. Repites el mismo bloque de código en varios sitios y, si encuentras un error en ese bloque, tienes que corregirlo en todos ellos. ¡Se convierte en un caos!
Aquí es donde entran las funciones (también conocidas como métodos).
Una función es como una herramienta especializada que guardas en tu caja de herramientas. Es un bloque de código con un nombre, diseñado para hacer una tarea muy concreta. En lugar de reescribir el código una y otra vez, simplemente "usas la herramienta" llamándola por su nombre.
Ventajas principales de usar funciones
- Reutilización: Escribes el código una vez y lo llamas tantas veces como quieras.
- Organización: Dividen un problema grande en problemas más pequeños y manejables. ¡Adiós al caos en
main! - Legibilidad: Un programa bien estructurado en funciones es mucho más fácil de leer y entender.
- Mantenimiento: Si necesitas corregir o mejorar una tarea, solo tienes que modificar su función y el cambio se aplicará en todos los sitios donde se use.
2. Anatomía de una Función: La Etiqueta de la Herramienta
Cada función tiene una "etiqueta" que nos dice todo lo que necesitamos saber sobre ella. Esta etiqueta es su declaración o cabecera.
[Modificadores] TipoDevuelto nombreDeLaFuncion(Lista de Parámetros)
Vamos a desglosarlo con una analogía:
| Parte de la Declaración | Analogía: La Etiqueta de la Herramienta | Ejemplo: public static int sumar(int a, int b) |
|---|---|---|
| Modificadores | Las "instrucciones de uso" (pública, estática...). | public static (Por ahora, siempre usaremos estos). |
| Tipo de Retorno | Lo que la herramienta te devuelve al terminar. | int (Esta herramienta te devolverá un número entero). |
| Nombre de la Función | El nombre de la herramienta. Debe ser descriptivo. | sumar (Claramente, esta herramienta sirve para sumar). |
| Parámetros | Los materiales que necesita la herramienta para trabajar. | (int a, int b) (Necesita dos números enteros para poder hacer su trabajo). |
Cuerpo {...} |
El mecanismo interno de la herramienta. Las instrucciones que ejecuta. | { int resultado = a + b; return resultado; } (Suma los materiales y devuelve el resultado). |
Ejemplo de código completo:
3. Funciones vs. Procedimientos: ¿Devuelves algo o solo actúas?
En nuestra caja de herramientas, tenemos dos tipos de especialistas:
3.1. Funciones (Las que devuelven un resultado)
Una función es una herramienta que, después de hacer su trabajo, te devuelve un resultado. Utiliza la palabra clave return para entregar ese resultado.
Aquí tienes otro ejemplo clásico de una función:
3.2. Procedimientos (Los que solo realizan una acción)
Un procedimiento es una herramienta que realiza una tarea, pero no devuelve ningún resultado. En Java, los identificamos porque su "Tipo de Retorno" es void (vacío).
| Característica | Función | Procedimiento |
|---|---|---|
| Propósito | Calcular y devolver un valor. | Ejecutar una serie de acciones. |
| Retorno | int, double, String, etc. |
void |
| Palabra Clave | Usa return valor; |
No suele usar return (o solo return;). |
| Uso Típico | variable = miFuncion(); o dentro de una expresión. |
miProcedimiento(); en una línea sola. |
4. Ámbito de las Variables: La Regla de la Habitación de Hotel
El ámbito o scope de una variable define dónde es visible y se puede utilizar. La regla de oro es muy simple:
"Cada función es su propia habitación de hotel"
Cuando entras en la habitación de hotel (llamas a una función), puedes usar todo lo que hay dentro: la cama, la mesa, la tele (las variables locales y los parámetros). Pero cuando sales de la habitación y cierras la puerta (la función termina), ya no puedes acceder a nada de lo que había dentro. Esas variables "desaparecen" para el resto del programa.
Esta encapsulación es fundamental, ya que garantiza que las funciones sean independientes y no interfieran unas con otras por accidente.
5. Paso de Parámetros: Fotocopias vs. Direcciones
Cuando llamamos a una función y le pasamos datos, la forma en que Java los entrega depende del tipo de dato. ¡Entender esto es crucial!
5.1. Paso por Valor: "Te paso una fotocopia" (Tipos Primitivos)
Cuando pasas un tipo primitivo (int, double, char, boolean...), Java no le da tu variable original a la función. En su lugar, le da una copia exacta, una fotocopia.
La función puede hacer lo que quiera con esa fotocopia (cambiarle el valor, usarla en cálculos...), pero tu variable original permanecerá intacta.
5.2. Paso por Referencia: "Te paso la dirección" (Arrays y Objetos)
Cuando pasas un array o un objeto, Java cambia de estrategia. En lugar de copiar toda la estructura (lo cual sería muy ineficiente), le pasa a la función la dirección de memoria donde se encuentra el objeto original.
La función recibe la dirección, va a la "casa" original y trabaja directamente sobre ella. Por lo tanto, cualquier cambio que la función haga en el array u objeto, afectará al original.
5.3. Llamada de Funciones desde otras Funciones (Composición)
La función main es solo el punto de entrada. El verdadero poder de la modularidad se demuestra cuando las funciones se llaman entre sí. A esto se le llama composición de funciones: se construyen operaciones complejas a partir de otras más simples.
Una función puede delegar parte de su lógica a otra función más especializada, a menudo llamada función auxiliar (o 'helper function').
Ejemplo: Calcular el precio final con IVA, delegando el cálculo del IVA a una función auxiliar.
Salida:
6. Buenas Prácticas al Crear Funciones
Reglas de Oro del Diseño de Funciones
- Principio de Responsabilidad Única: Una función debe hacer una sola cosa y hacerla bien. Si tu función se llama
calcularYMostrarNota, probablemente debería dividirse encalcularNota()ymostrarNota(). - Nombres Descriptivos: El nombre de una función debe ser un verbo o una acción que deje claro su propósito.
calcularPromedioes mucho mejor quefunc1ocalculo. - Pocos Parámetros: Intenta que tus funciones no necesiten demasiados "materiales". Si una función requiere más de 3 o 4 parámetros, puede ser una señal de que está haciendo demasiadas cosas.
- Comentarios
Javadoc: Documenta tus funciones. Explica brevemente qué hacen, qué significa cada parámetro y qué devuelven. Esto es de gran ayuda para ti y para otros programadores.
7. Ejemplo Práctico: Mini-Gestor de Calificaciones
Vamos a unir todo lo que hemos aprendido en un programa completo. Crearemos un pequeño gestor de notas que nos permitirá introducir las calificaciones de un alumno, calcular la media, encontrar la nota más alta y mostrar un informe final.
Este ejemplo te permitirá ver en acción:
- El
maincomo organizador. - Procedimientos (
void) para mostrar información. - Funciones que devuelven valores.
- Paso de parámetros por valor y por referencia.
Enunciado del Problema
Crear un programa que gestione las 5 notas de un alumno. El programa debe:
- Mostrar un mensaje de bienvenida.
- Solicitar al usuario que introduzca las 5 notas y guardarlas en un array.
- Calcular la nota media.
- Encontrar la nota más alta.
- Mostrar un informe completo con todas las notas, la media y la nota más alta.