Desafio JavaScript

Sistema de Formas Geométricas

Enunciado

Crie uma classe abstrata Forma com um campo privado #nome e um método area() que lança um erro 'Método area() deve ser implementado'. Adicione um getter nome. Em seguida, crie as classes Circulo e Retangulo que estendem Forma. Circulo recebe raio e implementa area() retornando π * raio². Retangulo recebe largura e altura e implementa area() retornando largura * altura. Ambas devem chamar super com o nome da forma. Crie uma função imprimirArea(forma) que recebe uma forma e imprime "A área do [nome] é [area]". Instancie um círculo de raio 3 e um retângulo de 4x5, e chame imprimirArea para cada um.

Requisitos

  • Forma deve ter campo privado #nome, getter nome e método area() que lança erro.
  • Circulo e Retangulo devem estender Forma e implementar area().
  • Os construtores de Circulo e Retangulo devem chamar super com o nome.
  • A função imprimirArea deve usar o getter nome e o método area().
  • A saída deve mostrar as áreas calculadas corretamente.

Código inicial

class Forma {
  // seu código aqui
}

class Circulo extends Forma {
  // seu código aqui
}

class Retangulo extends Forma {
  // seu código aqui
}

function imprimirArea(forma) {
  // seu código aqui
}

const circulo = new Circulo(3);
imprimirArea(circulo);
const retangulo = new Retangulo(4, 5);
imprimirArea(retangulo);

Saída esperada

A área do Círculo é 28.274333882308138
A área do Retângulo é 20
Ver dica

Use Math.PI para o valor de π. No método area() da classe Forma, lance new Error('Método area() deve ser implementado').

Mostrar solução
class Forma {
  #nome;

  constructor(nome) {
    this.#nome = nome;
  }

  get nome() {
    return this.#nome;
  }

  area() {
    throw new Error('Método area() deve ser implementado');
  }
}

class Circulo extends Forma {
  #raio;

  constructor(raio) {
    super('Círculo');
    this.#raio = raio;
  }

  area() {
    return Math.PI * this.#raio ** 2;
  }
}

class Retangulo extends Forma {
  #largura;
  #altura;

  constructor(largura, altura) {
    super('Retângulo');
    this.#largura = largura;
    this.#altura = altura;
  }

  area() {
    return this.#largura * this.#altura;
  }
}

function imprimirArea(forma) {
  console.log(`A área do ${forma.nome} é ${forma.area()}`);
}

const circulo = new Circulo(3);
imprimirArea(circulo);
const retangulo = new Retangulo(4, 5);
imprimirArea(retangulo);

Passo a passo

  1. A classe Forma tem um campo privado #nome, um construtor que o define e um getter nome.
  2. O método area() lança um erro para forçar subclasses a implementá-lo.
  3. Circulo estende Forma, chama super('Círculo') e armazena #raio.
  4. O método area() de Circulo calcula a área usando Math.PI e o raio ao quadrado.
  5. Retangulo estende Forma, chama super('Retângulo') e armazena #largura e #altura.
  6. O método area() de Retangulo multiplica largura por altura.
  7. A função imprimirArea acessa forma.nome (getter) e forma.area() (método) e imprime a mensagem.
  8. Criamos as instâncias e chamamos imprimirArea para cada uma.

Por que funciona

A classe Forma define um contrato: toda forma tem um nome e um método area(). As subclasses implementam area() de acordo com sua geometria. O uso de super garante que o nome seja inicializado corretamente. O polimorfismo permite que imprimirArea funcione com qualquer objeto que herde de Forma.

Erros comuns

  • Não chamar super no construtor da subclasse: erro ao usar this.
  • Esquecer de implementar area() na subclasse: ao chamar, o método da classe pai lançará erro.
  • Tentar acessar circulo.#raio fora da classe: erro de sintaxe.
  • Usar Math.pi em vez de Math.PI: Math.pi é undefined, resultando em NaN.

Outra forma de resolver

Se não precisar de campo privado, pode usar propriedades públicas. Mas a versão com # protege os dados internos.

Saída esperada

A área do Círculo é 28.274333882308138
A área do Retângulo é 20