Saltar al contenido principal
eLearner.app
Módulo 3 · Lección 2 de 26/14 en el curso~15 min
Lecciones del módulo (2/2)

Polimorfismo y Clases Abstractas

El polimorfismo y las clases abstractas son conceptos avanzados de la programación orientada a objetos que permiten escribir código flexible, extensible e independiente de las implementaciones específicas.

El Polimorfismo

El término polimorfismo (muchas formas) se refiere a la capacidad de tratar objetos de diferentes clases como si pertenecieran a un tipo común. En Java, una variable de tipo superclase puede almacenar una referencia a un objeto de cualquier subclase.

Code
class Animal {
    public void makeSound() {
        System.out.println("Verso...");
    }
}

class Dog extends Animal {
    public void makeSound() {
        System.out.println("Woof");
    }
}

class Cat extends Animal {
    public void makeSound() {
        System.out.println("Miao");
    }
}

Gracias al polimorfismo, podemos hacer esto:

Code
Animal myAnimal1 = new Dog(); // Polimorfismo
Animal myAnimal2 = new Cat(); // Polimorfismo

myAnimal1.makeSound(); // Esegue il metodo di Dog (Woof)
myAnimal2.makeSound(); // Esegue il metodo di Cat (Miao)

La decisión de qué método invocar ocurre en tiempo de ejecución (Late Binding o dynamic dispatch) en función del objeto real y no del tipo de la variable de referencia.

Clases Abstractas (abstract)

Una clase abstracta es una clase marcada con la palabra clave abstract que no puede ser instanciada directamente (no puedes hacer new MyAbstractClass()). Sirve como un "modelo parcial" para otras clases.

Métodos Abstractos

Una clase abstracta puede contener métodos abstractos: métodos declarados sin cuerpo (sin llaves y sin código), que terminan con un punto y coma. Las subclases no abstractas están obligadas a implementar todos los métodos abstractos heredados.

Code
abstract class Shape {
    String color;

    // Metodo astratto (senza corpo)
    public abstract double getArea();
}

class Circle extends Shape {
    double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    // Obbligatorio implementare getArea
    @Override
    public double getArea() {
        return Math.PI * radius * radius;
    }
}

Dynamic Binding / Late Binding

¿Cómo sabe Java qué método ejecutar en tiempo de ejecución? Este proceso se conoce como Late Binding (o Dynamic Binding). A diferencia de la sobrecarga (resuelta en tiempo de compilación), el compilador no sabe qué método específico se ejecutará. En su lugar, genera una instrucción de llamada genérica. En tiempo de ejecución, la Java Virtual Machine (JVM) examina el objeto real en memoria e invoca la implementación del método definida en la clase de ese objeto.

Clases Abstractas y Falta de Implementación

Si una subclase hereda de una clase abstracta, tiene dos opciones:

  1. Implementar todos los métodos abstractos: en este caso, la clase puede ser una clase normal (concreta) e instanciarse.
  2. Declararse abstracta: si la subclase no proporciona una implementación para todos los métodos abstractos heredados, debe declararse a su vez con la palabra clave abstract.
Code
abstract class Animal {
    public abstract void makeSound();
}

// Questa classe DEVE essere astratta perché non implementa makeSound()
abstract class Canine extends Animal {
    // Eredita makeSound() ma non lo implementa
}

Pruébalo tú

Ejercicio#java.m3.l2.e1
Intentos: 0Cargando...

Declara una variable s de tipo Shape y asígnale un nuevo objeto Circle usando el polimorfismo.

Cargando editor...
Mostrar pista

Escribe `Shape s = new Circle();` para usar el tipo base como tipo del referencia.

Solución disponible después de 3 intentos

Ejercicio#java.m3.l2.e2
Intentos: 0Cargando...

Haz que la clase Shape sea abstracta y añade el método abstracto double getArea(). Luego completa Square para que extienda Shape e implemente getArea() devolviendo side * side.

Cargando editor...
Mostrar pista

Declara `public abstract double getArea();` en Shape. En Square, añade `@Override public double getArea() { return side * side; }`.

Solución disponible después de 3 intentos

Ejercicio#java.m3.l2.e3
Intentos: 0Cargando...

Declara en el main un arreglo de tipo Shape[] que contenga un objeto Circle con radio 2.0 y un objeto Square con lado 3.0. A continuación, usa un bucle (for o for-each) para imprimir en la consola el área de cada forma invocando el método getArea().

Cargando editor...
Mostrar pista

Declara el arreglo con `Shape[] shapes = { new Circle(2.0), new Square(3.0) };` y recórrelo con un bucle `for (Shape s : shapes)` imprimiendo `s.getArea()`.

Solución disponible después de 3 intentos