Fácil Java

Formas geométricas polimórficas

Enunciado

Crie uma hierarquia de classes para representar formas geométricas. A superclasse Forma deve ter um método area() que retorna double. As subclasses Circulo e Retangulo devem implementar area() com as fórmulas corretas. No main, crie um array de Forma com um círculo de raio 2.0 e um retângulo de base 3.0 e altura 4.0. Percorra o array e imprima a área de cada forma.

Requisitos

  • A classe Forma deve ser abstrata ou ter método area() que retorna 0.
  • Circulo calcula área como Math.PI * raio * raio.
  • Retangulo calcula área como base * altura.
  • O programa imprime as áreas com duas casas decimais.

Código inicial

abstract class Forma {
    abstract double area();
}

// TODO: crie Circulo e Retangulo

public class Main {
    public static void main(String[] args) {
        // TODO: crie array de Forma e imprima as áreas
    }
}

Saída esperada

Área do círculo: 12,57
Área do retângulo: 12,00
Ver dica

Use String.format("%.2f", valor) para formatar com duas casas decimais. Lembre-se de que o separador decimal pode ser vírgula dependendo do locale, mas o esperado é ponto. Para garantir ponto, use String.format(Locale.US, "%.2f", valor).

Mostrar solução
import java.util.Locale;

abstract class Forma {
    abstract double area();
}

class Circulo extends Forma {
    private double raio;

    Circulo(double raio) {
        this.raio = raio;
    }

    @Override
    double area() {
        return Math.PI * raio * raio;
    }
}

class Retangulo extends Forma {
    private double base;
    private double altura;

    Retangulo(double base, double altura) {
        this.base = base;
        this.altura = altura;
    }

    @Override
    double area() {
        return base * altura;
    }
}

public class Main {
    public static void main(String[] args) {
        Forma[] formas = { new Circulo(2.0), new Retangulo(3.0, 4.0) };

        for (Forma f : formas) {
            // Despacho dinâmico: area() chama a implementação correta
            double area = f.area();
            String tipo = (f instanceof Circulo) ? "círculo" : "retângulo";
            System.out.printf(Locale.US, "Área do %s: %.2f%n", tipo, area);
        }
    }
}

Passo a passo

  1. Definimos a classe abstrata Forma com o método abstrato area(). Isso estabelece o contrato que todas as formas devem seguir.
  2. Circulo estende Forma, armazena o raio e implementa area() usando Math.PI * raio * raio.
  3. Retangulo também estende Forma, armazena base e altura e implementa area() como base * altura.
  4. No main, criamos um array do tipo Forma[] contendo um Circulo e um Retangulo. Isso é possível porque ambos são subtipos de Forma.
  5. Iteramos sobre o array com um for-each. A variável f é do tipo Forma, mas o objeto real é de uma subclasse.
  6. Dentro do loop, chamamos f.area(). O despacho dinâmico garante que a implementação correta seja executada para cada objeto.
  7. Usamos f instanceof Circulo para determinar o tipo e imprimir a mensagem adequada. Isso não afeta o cálculo da área, que já é polimórfico.
  8. Formatamos a saída com String.format usando Locale.US para garantir o ponto decimal.

Por que funciona

O polimorfismo permite tratar objetos de diferentes subclasses de forma uniforme através de uma referência de superclasse. O método area() é sobrescrito em cada subclasse, e a JVM decide qual versão chamar com base no tipo real do objeto em tempo de execução. Assim, o mesmo código (f.area()) produz resultados diferentes conforme o objeto.

Erros comuns

  • Esquecer de sobrescrever area(): se a subclasse não implementar o método abstrato, o código não compila. Certifique-se de usar @Override.
  • Usar == para comparar tipos: f instanceof Circulo é correto; f.getClass() == Circulo.class também funciona, mas é menos idiomático e não lida com subclasses.
  • Formatação com vírgula: sem Locale.US, String.format("%.2f", 12.57) pode imprimir 12,57 em locales que usam vírgula. Use Locale.US para garantir o ponto.

Outra forma de resolver

Poderia-se usar uma interface Forma em vez de classe abstrata. A escolha depende se há código comum a ser compartilhado. Exemplo:

interface Forma {
    double area();
}

Isso é preferível quando não há estado ou comportamento comum.

Saída esperada

Área do círculo: 12.57
Área do retângulo: 12.00