Uma lanchonete deseja um sistema de informação para gerenciar suas atividades. A lanchonete possui o gerente, cozinheiros e aténdentes. Eles possuem nome, cpf, salario. A lanchonete oferece os seguintes produtos: lanches, refrigerante e jantar por reserva.
Os seguintes tipos de lanches: pizza, sanduiche e cupcake. As pizzas podem ter borda ou não. Os lanches possuem id, preço, data de validade e peso. O sistema deverá criar um pedido que será composto pelo nome do cliente, nome do atendente, lanches comprados, valor total e data. O sistema deve gerar uma nota fiscal(print) para o cliente com os dados do pedido. A lanchonete também trabalha com encomendas. Cada encomenda tem o nome do cliente, os lanches, valor total e data de entrega.
Para o jantar o cliente entra em contato com a lanchonete e faz a reserva, com as informações data e quantidade de pessoas.
Crie uma classe para teste para testar o sistema lanchonete. Crie um pedido e faça uma reserva de jantar.
*Use herança e encapsulamento
*Defina as relações entre as classes.
*Extra: Use construtores sobrecarregados
*Extra: Sobrescreva métodos na subclasse da superclasse

Passo 1

O enunciado pede que a gente construa um pequeno sistema orientado a objeto (classes) para uma lanchonete. Pontos que o enunciado traz e que precisamos implementar:
  • Pessoas da lanchonete: gerente, cozinheiros e atendentes. Cada um tem nome, CPF e salário.
  • Produtos que a lanchonete oferece: lanches (tipos: pizza, sanduíche e cupcake), refrigerante e jantar por reserva.
  • Requisitos dos lanches: têm id, preço, data de validade e peso. As pizzas ainda têm a característica “borda” (tem ou não).
  • Deve existir a noção de pedido: composto por nome do cliente, nome do atendente, lista de lanches comprados, valor total e data. O sistema deve gerar uma nota fiscal (imprimir) do pedido.
  • Encomendas: têm nome do cliente, lanches, valor total e data de entrega.
  • Jantar por reserva: cliente informa data e quantidade de pessoas (reserva).
  • Pedir para usar herança e encapsulamento.
  • Extra: construtores sobrecarregados.
  • Extra: sobrescrever métodos na subclasse (override).
Informações relevantes extraídas do enunciado:
  • Precisamos modelar classes para funcionários (com herança), classes para lanches (com herança) e classes para Pedido, Encomenda e ReservaJantar.
  • Pedidos trabalham com listas de lanches.
  • Precisamos de métodos para calcular total e imprimir nota fiscal (print).
  • Devemos aplicar encapsulamento: campos privados e acesso via getters/setters.

Passo 2

Decisão sobre o projeto (relação entre classes e por que):
  • Vou criar uma superclasse abstrata Employee que tem os campos comuns (nome, cpf, salario). As subclasses serão Gerente, Cozinheiro e Atendente. Cada subclasse pode sobrescrever um método (por exemplo, getCargo ou toString) — isso mostra override.
  • Para os produtos, vou criar uma classe abstrata Lanche com campos comuns (id, preco, validade, peso). Subclasses: Pizza, Sanduiche e Cupcake. A Pizza terá o campo adicional booleano borda. Vou mostrar construtores sobrecarregados em Lanche e em Pizza.
  • Terei também uma classe Refrigerante (opcional) como outro tipo de produto (não-herdando de Lanche, porque refrigerante não tem peso e validade no mesmo sentido; mas poderia herdar se desejado).
  • Pedido: classe com nomeCliente, nomeAtendente, lista de Lanche, data e método para calcular valor total e imprimir nota fiscal.
  • Encomenda: similar ao Pedido, mas com dataEntrega.
  • ReservaJantar: classe com nomeCliente, dataReserva e quantidadePessoas, com método para confirmar.
  • Encapsulamento: todos os campos privados, acesso via getters/setters. Métodos públicos para operações (adicionar lanche, calcular total, imprimir nota).
  • Sobrescritas (override): toString e um método getDescricao em cada subclasse de Lanche para mostrar detalhes específicos.
  • Construtores sobrecarregados: vou fornecer pelo menos dois construtores em Lanche (um com validade, outro sem) e em Employee (um com salário, outro sem salário) e em Pizza (com e sem borda explicitada).
Agora vou mostrar as classes essenciais (código em Java), explicando o que cada parte faz.

Passo 3

Classe Employee e subclasses (herança e encapsulamento). Explicação: usamos uma superclasse abstrata para obrigar que todos os empregados tenham os campos comuns. Cada campo é privado (encapsulamento). Fornecemos getters/setters públicos. As subclasses sobrescrevem toString para mostrar o cargo.
Código (Employee.java, Gerente.java, Cozinheiro.java, Atendente.java):
import java.util.Objects;

public abstract class Employee {
    private String nome;
    private String cpf;
    private double salario;

    // Construtor padrão
    public Employee(String nome, String cpf, double salario) {
        this.nome = nome;
        this.cpf = cpf;
        this.salario = salario;
    }

    // Construtor sobrecarregado (salário opcional)
    public Employee(String nome, String cpf) {
        this(nome, cpf, 0.0);
    }

    // Getters e setters (encapsulamento)
    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public String getCpf() {
        return cpf;
    }

    public void setCpf(String cpf) {
        this.cpf = cpf;
    }

    public double getSalario() {
        return salario;
    }

    public void setSalario(double salario) {
        this.salario = salario;
    }

    // Método que pode ser sobrescrito pelas subclasses
    public String getCargo() {
        return "Funcionário";
    }

    @Override
    public String toString() {
        return getCargo() + ": " + nome + " (CPF: " + cpf + ", Salário: " + salario + ")";
    }
}

public class Gerente extends Employee {
    public Gerente(String nome, String cpf, double salario) {
        super(nome, cpf, salario);
    }

    @Override
    public String getCargo() {
        return "Gerente";
    }
}

public class Cozinheiro extends Employee {
    public Cozinheiro(String nome, String cpf, double salario) {
        super(nome, cpf, salario);
    }

    @Override
    public String getCargo() {
        return "Cozinheiro";
    }
}

public class Atendente extends Employee {
    public Atendente(String nome, String cpf, double salario) {
        super(nome, cpf, salario);
    }

    // Exemplo de construtor sobrecarregado
    public Atendente(String nome, String cpf) {
        super(nome, cpf);
    }

    @Override
    public String getCargo() {
        return "Atendente";
    }
}
Explicação didática curta:
  • Por que abstrata? Para que não se crie um Employee genérico — queremos sempre um tipo específico (Gerente, Cozinheiro, Atendente).
  • Encapsulamento: campos privados e métodos públicos controlam acesso e evitam manipulação direta.

Passo 4

Classe Lanche e subclasses (Pizza, Sanduiche, Cupcake). Explicação: Lanche é abstrata porque não queremos instanciar um “Lanche” genérico sem tipo. Campos privados: id, preco, validade, peso. Métodos para obter preço e descrição. Sobrescrita (override) de getDescricao e toString nas subclasses para apresentar informações específicas.
Código (Lanche.java, Pizza.java, Sanduiche.java, Cupcake.java):
import java.time.LocalDate;

public abstract class Lanche {
    private String id;
    private double preco;
    private LocalDate validade;
    private double peso; // em gramas, por exemplo

    // Construtor completo
    public Lanche(String id, double preco, LocalDate validade, double peso) {
        this.id = id;
        this.preco = preco;
        this.validade = validade;
        this.peso = peso;
    }

    // Construtor sobrecarregado (sem validade informada)
    public Lanche(String id, double preco, double peso) {
        this(id, preco, null, peso);
    }

    // Getters e setters
    public String getId() {
        return id;
    }

    public double getPreco() {
        return preco;
    }

    public void setPreco(double preco) {
        this.preco = preco;
    }

    public LocalDate getValidade() {
        return validade;
    }

    public void setValidade(LocalDate validade) {
        this.validade = validade;
    }

    public double getPeso() {
        return peso;
    }

    public void setPeso(double peso) {
        this.peso = peso;
    }

    // Método que será sobrescrito para dar descrição específica
    public String getDescricao() {
        return "Lanche genérico (id=" + id + ")";
    }

    @Override
    public String toString() {
        String v = (validade == null) ? "indefinida" : validade.toString();
        return getDescricao() + " | Preço: " + String.format("%.2f", preco) + " | Validade: " + v + " | Peso: " + peso + "g";
    }
}

public class Pizza extends Lanche {
    private boolean borda;

    // Construtor com validade
    public Pizza(String id, double preco, LocalDate validade, double peso, boolean borda) {
        super(id, preco, validade, peso);
        this.borda = borda;
    }

    // Construtor sobrecarregado (sem validade)
    public Pizza(String id, double preco, double peso, boolean borda) {
        super(id, preco, peso);
        this.borda = borda;
    }

    public boolean hasBorda() {
        return borda;
    }

    public void setBorda(boolean borda) {
        this.borda = borda;
    }

    @Override
    public String getDescricao() {
        return "Pizza (id=" + getId() + ", borda=" + (borda ? "sim" : "não") + ")";
    }
}

public class Sanduiche extends Lanche {
    public Sanduiche(String id, double preco, LocalDate validade, double peso) {
        super(id, preco, validade, peso);
    }

    public Sanduiche(String id, double preco, double peso) {
        super(id, preco, peso);
    }

    @Override
    public String getDescricao() {
        return "Sanduíche (id=" + getId() + ")";
    }
}

public class Cupcake extends Lanche {
    public Cupcake(String id, double preco, LocalDate validade, double peso) {
        super(id, preco, validade, peso);
    }

    public Cupcake(String id, double preco, double peso) {
        super(id, preco, peso);
    }

    @Override
    public String getDescricao() {
        return "Cupcake (id=" + getId() + ")";
    }
}
Explicação didática curta:
  • Observe os dois construtores em Lanche: um com validade e outro sem — isso é sobrecarga de construtor.
  • Em Pizza temos outro construtor sobrecarregado: com e sem validade (reaproveitamos o construtor da superclasse).

Passo 5

Pedido, Encomenda e ReservaJantar. Explicação: estas classes controlam operações típicas (calcular total, imprimir nota, confirmar reserva). Usaremos List<Lanche> para armazenar os lanches do pedido. O método calcularTotal soma os preços dos lanches — simples e direto.
Código (Pedido.java, Encomenda.java, ReservaJantar.java):
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

public class Pedido {
    private String nomeCliente;
    private String nomeAtendente;
    private List<Lanche> lanches;
    private double valorTotal;
    private LocalDate data;

    public Pedido(String nomeCliente, String nomeAtendente, List<Lanche> lanches, LocalDate data) {
        this.nomeCliente = nomeCliente;
        this.nomeAtendente = nomeAtendente;
        // fazemos uma cópia defensiva da lista para não expor a lista interna
        this.lanches = new ArrayList<>(lanches);
        this.data = data;
        this.valorTotal = calcularTotal();
    }

    // Método que soma os preços dos lanches
    private double calcularTotal() {
        double total = 0.0;
        for (Lanche l : lanches) {
            total += l.getPreco();
        }
        return total;
    }

    public void imprimirNotaFiscal() {
        System.out.println("------ NOTA FISCAL ------");
        System.out.println("Cliente: " + nomeCliente);
        System.out.println("Atendente: " + nomeAtendente);
        System.out.println("Data: " + data);
        System.out.println("Itens:");
        for (Lanche l : lanches) {
            System.out.println("  - " + l.toString());
        }
        System.out.println("Valor total: R$ " + String.format("%.2f", valorTotal));
        System.out.println("-------------------------");
    }

    // Getters (se quiser atualizar os lanches, podemos criar métodos específicos)
    public double getValorTotal() {
        return valorTotal;
    }

    public List<Lanche> getLanches() {
        return new ArrayList<>(lanches);
    }
}

public class Encomenda {
    private String nomeCliente;
    private List<Lanche> lanches;
    private double valorTotal;
    private LocalDate dataEntrega;

    public Encomenda(String nomeCliente, List<Lanche> lanches, LocalDate dataEntrega) {
        this.nomeCliente = nomeCliente;
        this.lanches = new ArrayList<>(lanches);
        this.dataEntrega = dataEntrega;
        this.valorTotal = calcularTotal();
    }

    private double calcularTotal() {
        double total = 0.0;
        for (Lanche l : lanches) {
            total += l.getPreco();
        }
        return total;
    }

    public void imprimirEncomenda() {
        System.out.println("---- ENCOMENDA ----");
        System.out.println("Cliente: " + nomeCliente);
        System.out.println("Data de entrega: " + dataEntrega);
        System.out.println("Itens:");
        for (Lanche l : lanches) {
            System.out.println("  - " + l.toString());
        }
        System.out.println("Valor total: R$ " + String.format("%.2f", valorTotal));
        System.out.println("-------------------");
    }
}

public class ReservaJantar {
    private String nomeCliente;
    private LocalDate dataReserva;
    private int quantidadePessoas;

    public ReservaJantar(String nomeCliente, LocalDate dataReserva, int quantidadePessoas) {
        this.nomeCliente = nomeCliente;
        this.dataReserva = dataReserva;
        this.quantidadePessoas = quantidadePessoas;
    }

    public void confirmarReserva() {
        System.out.println("=== RESERVA DE JANTAR ===");
        System.out.println("Cliente: " + nomeCliente);
        System.out.println("Data: " + dataReserva);
        System.out.println("Número de pessoas: " + quantidadePessoas);
        System.out.println("Reserva confirmada! Obrigado.");
        System.out.println("=========================");
    }

    // Getters e setters
    public LocalDate getDataReserva() {
        return dataReserva;
    }

    public int getQuantidadePessoas() {
        return quantidadePessoas;
    }
}
Explicação didática curta:
  • Ao construir o pedido, calculamos o total automaticamente e armazenamos em valorTotal.
  • imprimirNotaFiscal mostra como gerar a “nota fiscal” (um simples print formatado).
  • Encomenda é análoga ao Pedido, mas com dataEntrega.
  • ReservaJantar tem método confirmarReserva para simular a confirmação.

Passo 6

Observações didáticas sobre encapsulamento, herança, sobrecarga e sobrescrita:
  • Encapsulamento: todos os campos importantes foram declarados como private. Para acessar ou modificar, usamos getters/setters. Isso nos permite validar mudanças no futuro (ex.: impedir salário negativo).
  • Herança: Employee é superclasse; Gerente, Cozinheiro e Atendente herdam campos e métodos. Lanche é superclasse abstrata; Pizza, Sanduiche, Cupcake herdam.
  • Sobrescrita (override): sobrescrevemos getCargo()/toString() em Employee subclasses, e getDescricao() em cada Lanche. Isso permite comportamento específico por tipo.
  • Sobrecarga de construtores: Lanche tem dois construtores; Pizza também; Atendente tem versão com e sem salário. A sobrecarga permite diferentes formas de criar objetos conforme a informação disponível.
  • Boas práticas: usamos cópias defensivas de listas no construtor (new ArrayList<>(lanches)) para evitar que a lista interna seja alterada fora da classe.

Passo 7

Como testar: criar uma classe de teste (com main) que:
  • cria um atendente (Atendente),
  • cria alguns lanches (Pizza, Sanduiche, Cupcake),
  • monta uma lista de lanches,
  • cria um Pedido com esses lanches e chama imprimirNotaFiscal(),
  • cria uma ReservaJantar e chama confirmarReserva().
Abaixo, na seção final (

Resposta

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

public class TestLanchonete {
    public static void main(String[] args) {
        // Criando um atendente (poderia ser criado também gerente e cozinheiro)
        Atendente atendente = new Atendente("Maria Silva", "11122233344", 1800.0);

        // Criando alguns lanches
        Pizza pizza = new Pizza("P001", 29.90, LocalDate.of(2025, 12, 31), 800, true);
        Sanduiche sanduiche = new Sanduiche("S001", 12.50, LocalDate.of(2025, 11, 30), 250);
        Cupcake cupcake = new Cupcake("C001", 5.00, LocalDate.of(2025, 10, 15), 80);

        // Montando a lista de lanches comprados
        List<Lanche> lanches = new ArrayList<>();
        lanches.add(pizza);
        lanches.add(sanduiche);
        lanches.add(cupcake);

        // Criando um pedido
        Pedido pedido = new Pedido("João Pereira", atendente.getNome(), lanches, LocalDate.now());

        // Imprimindo a nota fiscal (print)
        pedido.imprimirNotaFiscal();

        // Criando uma reserva de jantar
        ReservaJantar reserva = new ReservaJantar("Ana Costa", LocalDate.of(2025, 11, 20), 4);
        reserva.confirmarReserva();

        // Exemplo de encomenda (opcional)
        Encomenda encomenda = new Encomenda("Carlos Souza", lanches, LocalDate.of(2025, 10, 5));
        encomenda.imprimirEncomenda();
    }
}

Exercícios relacionados