Menu
Coddy logo textTech

Clases y métodos abstractos

Parte de la sección Programación Orientada a Objetos del Journey de Java de Coddy. Lección 32 de 87.

A veces quieres definir una clase que sirva como un modelo pero que nunca deba ser instanciada directamente. Por ejemplo, una clase Shape genérica tiene sentido como clase padre, pero ¿cómo se vería una "forma" sin una forma específica? Aquí es donde entran las clases abstractas.

Una clase abstracta se declara con la palabra clave abstract y no puede ser instanciada. Puede contener tanto métodos regulares con implementaciones como métodos abstractos que no tienen cuerpo:

public abstract class Shape {
    protected String color;
    
    public Shape(String color) {
        this.color = color;
    }
    
    // Método abstracto - sin implementación
    public abstract double getArea();
    
    // Método regular - tiene implementación
    public String getColor() {
        return color;
    }
}

Los métodos abstractos declaran qué debe hacer una subclase, pero no cómo. Cualquier clase no abstracta que extienda una clase abstracta debe proporcionar implementaciones para todos los métodos abstractos:

public class Circle extends Shape {
    private double radius;
    
    public Circle(String color, double radius) {
        super(color);
        this.radius = radius;
    }
    
    @Override
    public double getArea() {
        return Math.PI * radius * radius;
    }
}

Aún puedes usar clases abstractas como tipos de referencia, lo que permite el polimorfismo:

Shape shape = new Circle("red", 5.0);
System.out.println(shape.getArea());  // Llama a la implementación de Circle

Las clases abstractas son ideales cuando las subclases comparten código común, pero cada una debe implementar ciertos comportamientos de manera diferente. Imponen un contrato al mismo tiempo que permiten la reutilización de código.

challenge icon

Desafío

Fácil

Construyamos un sistema de electrodomésticos que demuestre el poder de las clases abstractas. Crearás una clase base Appliance que define lo que todo electrodoméstico debe hacer, mientras permite que los tipos específicos de electrodomésticos decidan exactamente cómo hacerlo.

Organizarás tu código en cuatro archivos:

  • Appliance.java: Crea una clase abstracta que sirva como modelo para todos los electrodomésticos. Cada electrodoméstico tiene un campo brand (String) y un campo wattage (int). Incluye un constructor que inicialice ambos campos, métodos getter para cada uno y un método normal getInfo() que devuelva: [brand] - [wattage]W. Define un método abstracto operate() que las subclases deban implementar; esto representa cómo realiza cada electrodoméstico su función principal.
  • WashingMachine.java: Crea una clase concreta que extienda Appliance. Las lavadoras tienen un campo adicional capacity (int) que representa el tamaño de la carga en kg. Usa super para gestionar la inicialización de la clase padre. Implementa el método operate() para imprimir: [brand] washing machine is washing [capacity]kg of clothes
  • Microwave.java: Crea otra clase concreta que extienda Appliance. Los microondas tienen un campo power (int) que representa el porcentaje del nivel de potencia. Implementa operate() para imprimir: [brand] microwave is heating at [power]% power
  • Main.java: Reúne todo usando polimorfismo. Recibirás cinco entradas: un nombre de marca, la potencia en vatios, la capacidad de la lavadora, otro nombre de marca y el nivel de potencia del microondas. Crea un WashingMachine y un Microwave, y luego guárdalos en un arreglo de referencias Appliance. Recorre el arreglo y, para cada electrodoméstico, imprime su información usando getInfo(), seguido de una llamada a operate().

Recibirás cinco entradas en este orden: primera marca (String), primera potencia en vatios (int), capacidad en kg (int), segunda marca (String) y nivel de potencia (int).

Tu salida debe mostrar cuatro líneas: para cada electrodoméstico, verás su línea de información seguida de su comportamiento de operación. Observa cómo la clase abstracta te permite tratar distintos electrodomésticos de manera uniforme, mientras cada uno funciona a su manera particular.

Pruébalo tú mismo

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // Leer entradas
        String brand1 = scanner.nextLine();
        int wattage1 = scanner.nextInt();
        int capacity = scanner.nextInt();
        scanner.nextLine(); // consumir nueva línea
        String brand2 = scanner.nextLine();
        int power = scanner.nextInt();
        
        // TODO: Crear un objeto WashingMachine con brand1, wattage1 y capacity
        
        // TODO: Crear un objeto Microwave con brand2, wattage1 (o el vataje apropiado) y power
        
        // TODO: Crear un arreglo de referencias de Appliance y almacenar ambos objetos
        
        // TODO: Recorrer el arreglo y para cada electrodoméstico:
        // - Imprimir su información usando getInfo()
        // - Llamar a operate()
    }
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos

Practica por tu cuenta: Compilador de Java online