Publicado en Tema 5 • Programación Orientada a Objetos

Ejercicio 13: Clase de Utilidades y el Modificador Final

Enunciado

El objetivo es crear una clase de utilidades que sirva para recopilar operaciones matemáticas y fórmulas "secretas" que utilizaremos a lo largo del curso.

Primero, implementaremos las operaciones básicas de una calculadora en la clase de utilidades para luego invocarlas desde la clase principal. Segundo, añadiremos fórmulas especiales (como elegir un alumno al azar o calcular una puntuación) que deben estar protegidas para que nadie pueda modificarlas si intentan extender nuestra clase.

Concepto clave: Para este ejercicio es fundamental aprender a utilizar el modificador final correctamente.
---

Solución

Dividiremos la solución en dos clases: Utilidades, donde reside la lógica compartida, y Calculadora, que actúa como interfaz de usuario por consola.

1. Clase Utilidades

En esta clase definimos métodos estáticos para que puedan ser usados sin instanciar la clase. Fíjate en el uso de final para las fórmulas que queremos proteger.

package Tema5.Ejercicios.ejercicio13;

import java.util.Random;

public class Utilidades {
    // Operaciones básicas
    public static double sumar(double a, double b) {
        return a + b;
    }

    public static double restar(double a, double b) {
        return a - b;
    }

    public static double multiplicar(double a, double b) {
        return a * b;
    }

    public static double dividir(double a, double b) {
        if (b != 0) {
            return a / b;
        }
        return Double.NaN;
    }

    // Fórmulas "secretas" protegidas con el modificador final
    public static final String obtenerAlumnoAlAzar(String[] alumnos) {
        Random rand = new Random();
        int indice = rand.nextInt(alumnos.length);
        return alumnos[indice];
    }

    public static final int calcularPuntuacionJuego(int puntos) {
        return puntos * 1000 + 50;
    }
}

2. Clase Calculadora (Main)

Esta clase gestiona el menú y utiliza los métodos de la clase anterior. Al ser métodos estáticos, los llamamos directamente como Utilidades.sumar().

package Tema5.Ejercicios.ejercicio13;

import java.util.Scanner;

public class Calculadora {

    public static void menu() {
        System.out.println("\n--- CALCULADORA ---");
        System.out.println("1. Suma");
        System.out.println("2. Resta");
        System.out.println("3. Multiplicación");
        System.out.println("4. División");
        System.out.println("5. Salir");
        System.out.print("Selecciona una opción: ");
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int opcion = 0;
        double num1 = 0, num2 = 0;

        do {
            menu();
            opcion = sc.nextInt();

            if (opcion >= 1 && opcion <= 4) {
                System.out.print("Introduce el primer número: ");
                num1 = sc.nextDouble();
                System.out.print("Introduce el segundo número: ");
                num2 = sc.nextDouble();
            }

            switch (opcion) {
                case 1:
                    System.out.println("Resultado: " + Utilidades.sumar(num1, num2));
                    break;
                case 2:
                    System.out.println("Resultado: " + Utilidades.restar(num1, num2));
                    break;
                case 3:
                    System.out.println("Resultado: " + Utilidades.multiplicar(num1, num2));
                    break;
                case 4:
                    double resultadoDividir = Utilidades.dividir(num1, num2);
                    if (Double.isNaN(resultadoDividir)) {
                        System.out.println("Error: No se puede dividir por cero.");
                    } else {
                        System.out.println("Resultado: " + resultadoDividir);
                    }
                    break;
                case 5:
                    System.out.println("Saliendo de la calculadora...");
                    break;
                default:
                    System.out.println("Opción incorrecta.");
            }
        } while (opcion != 5);
        sc.close();
    }
}

Uso del modificador final

En este ejercicio, hemos aplicado el modificador final en los métodos de fórmulas secretas. ¿Qué conseguimos con esto?

  • En un método: Impide que el método sea sobrescrito (overridden) en una subclase. Esto asegura que la lógica de la "fórmula secreta" permanezca idéntica aunque alguien herede de nuestra clase de utilidades.
  • En una clase: Si hubiéramos declarado public final class Utilidades, habríamos impedido que cualquier otra clase pudiera heredar de ella (extenderla).
  • En una variable: Convierte la variable en una constante, impidiendo que su valor sea reasignado una vez inicializado.