Uma clinica médica deseja um sistema de informação para gerenciar suas atividades. A clínica possui diversos médicos associados que atendem a diversas especialidades (ex., clínico geral, cardiologista, dermatologista, neurologista etc). De um médico deseja-se saber nome, número no Conselho Regional de Medicina (CRM), endereço, telefone, horários de atendimento (hora início e hora fim) em cada dia da semana, especialidades que ele atende e planos de saúde aos quais está conveniado. De uma especialidade deseja-se saber o nome e o código do CRM. De um plano de saúde deseja-se saber razão social, CNPJ, endereço e telefone.
Pacientes marcam consultas com médicos. Na marcação de uma consulta, deve-se informar o paciente, o médico, a data e a hora da consulta e o plano de saúde, caso a consulta não seja particular.
Caso o paciente não seja ainda cadastrado, deve informar nome, telefone, data de nascimento, endereço e profissão.
Durante uma consulta, o médico pode registrar três tipos de observações: textos a respeito das queixas do paciente, textos sobre as prescrições de medicamentos e exames solicitados e textos sobre resultados dos exames e respostas ao tratamento efetuado. Além disso, o médico pode consultar outras observações que ele mesmo tenha feito em consultas anteriores do paciente.
Crie uma classe para teste, contendo um método main. Dentro dele, crie médicos, pacientes e consultas.

  1. *Use herança(Pessoa, medico, medico/especialidade(ex.: cardiologista), paciente) e encapsulamento
    *Use construtores sobrecarregados
    *Sobrescreva métodos na subclasse da superclasse|

Passo 1

O que o enunciado pede (em termos claros) e as informações fornecidas:
  • Criar um sistema simples (modelo orientado a objetos) para uma clínica médica.
  • Informações exigidas:
    • Médico: nome, CRM, endereço, telefone, horários de atendimento (hora início e fim para cada dia da semana), especialidades, planos de saúde conveniados.
    • Especialidade: nome e código do CRM.
    • Plano de saúde: razão social, CNPJ, endereço, telefone.
    • Paciente: nome, telefone, data de nascimento, endereço, profissão (se ainda não cadastrado).
    • Consulta: paciente, médico, data e hora, plano de saúde (opcional, caso não seja particular).
    • Observações registradas durante consulta: textos sobre queixas, prescrições/exames solicitados, resultados/respostas ao tratamento — e o médico pode consultar observações antigas que ele mesmo tenha feito para o mesmo paciente.
  • Requisitos de implementação:
    • Usar herança: pelo menos as classes Pessoa → Médico, Paciente (e especialidades como classes separadas conforme necessário).
    • Encapsulamento (atributos privados + getters/setters).
    • Construtores sobrecarregados.
    • Sobrescrever métodos em subclasses (por exemplo, toString).
  • Além disso: criar uma classe de teste com método main que cria médicos, pacientes e consultas (e demonstra o uso).

Passo 2

Escolha de design (como vamos organizar as classes)
  • Criar uma superclasse abstrata Pessoa com os atributos comuns (nome, endereço, telefone) e métodos básicos.
  • Criar subclasses Medico e Paciente que estendem Pessoa. Cada uma terá atributos específicos.
  • Criar classes de apoio: Especialidade, PlanoSaude, Horario (para representar início/fim), Consulta, Observacao e um enum ObservacaoTipo.
  • Manter os atributos privados (encapsulamento). Fornecer getters e setters públicos quando necessário.
  • Usar construtores sobrecarregados para permitir criação com diferentes níveis de informação (por exemplo, Pessoa com apenas nome e telefone; Paciente com todos os dados).
  • Sobrescrever o método toString() nas subclasses para facilitar debugging/saída legível (isso cumpre o requisito “sobrescrever métodos na subclasse”).

Passo 3

Explicando detalhes importantes (encapsulamento e herança) — o que implementar e por quê
  • Encapsulamento: atributos privados evitam acesso direto. Em prova, escreva “private String nome;” e crie “public String getNome()” e “public void setNome(String nome)”. Isso protege o estado interno.
  • Herança: declarar “abstract class Pessoa” e depois “class Medico extends Pessoa”. Assim reutilizamos nome, endereço e telefone sem repetir código.
  • Construtores sobrecarregados: implementar mais de um construtor para cada classe. Exemplo em Paciente:
    • Paciente(String nome, String telefone)
    • Paciente(String nome, String telefone, LocalDate dataNascimento, String endereco, String profissao)
      Na prova, diga que sobrecarregou para facilitar testes e criação de objetos com dados parciais.
  • Sobrescrita (override): em cada subclasse fazer “@Override public String toString()” para mostrar informações relevantes. Em Java você escreve @Override acima do método para indicar a sobrescrita.

Passo 4

Como representar horários e dias da semana (detalhe prático)
  • Usar o enum DayOfWeek (de java.time) para mapear dias da semana.
  • Representar horário de atendimento com uma classe Horario contendo LocalTime inicio e LocalTime fim.
  • No médico, usar um Map<DayOfWeek, Horario> para armazenar o horário de cada dia.
  • Implementar métodos auxiliares como “adicionarHorario(DayOfWeek dia, Horario h)” e “isDisponivelEm(LocalDateTime dt)” que checa se o horário pedido está dentro do Horario do dia correspondente.

Passo 5

Como registrar observações durante uma consulta
  • Criar enum ObservacaoTipo com valores QUEIXA, PRESCRICAO, RESULTADO.
  • Cada Observacao tem tipo, texto e timestamp (LocalDateTime).
  • Consulta contém uma lista de Observacao. Permitir adicionar observações durante/apos a consulta.
  • O médico pode consultar observações anteriores que ELE mesmo fez para um paciente: implementar em Medico um método que recebe Paciente e retorna as Observacoes de consultas anteriores daquele paciente cujo autor é o próprio médico (comparando por referência ou por CRM).

Passo 6

Estruturar a classe Consulta
  • A Consulta guarda: Paciente paciente, Medico medico, LocalDateTime dataHora, PlanoSaude plano (nullable se particular), List<Observacao> observacoes.
  • Métodos úteis:
    • adicionarObservacao(Observacao obs)
    • listarObservacoes()
    • obterObservacoesPorTipo(ObservacaoTipo tipo)
  • Também é bom manter em Paciente uma lista de consultas para histórico (lista atualizada quando marcamos uma consulta).

Passo 7

Exemplo prático de uso (o que colocaremos no main)
  • Criar instâncias de Especialidade, PlanoSaude.
  • Criar Medico com horários, especialidades e convênios.
  • Criar Paciente (com construtor simples e completo para mostrar sobrecarga).
  • Criar Consulta ligando Paciente e Médico, com ou sem PlanoSaude.
  • Adicionar observações à consulta (dos três tipos).
  • Demonstrar o médico consultando observações anteriores feitas por ele para o paciente.
  • Imprimir informações para mostrar que tudo está funcionando.

Passo 8

Dicas rápidas para a prova (o que escrever e o que não esquecer)
  • Desenhe um pequeno diagrama UML: Pessoa ← Medico, Paciente; acompanhe com Especialidade e PlanoSaude ligados a Medico; Consulta liga Medico–Paciente.
  • Liste atributos principais em cada classe e métodos públicos principais (get/set, construtores, adicionarObservacao, marcarConsulta).
  • Declare visibilidade dos atributos (private) e anote “getters/setters” — isso demonstra encapsulamento.
  • Mostre pelo menos um método sobrescrito (toString) e um construtor sobrecarregado para cada subclasse.
  • Se pedirem código, entregue classes coesas e com nomes claros; faça o main demonstrando criação de objetos e algumas operações.

Resposta

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;

/**
 * Exemplo completo num único ficheiro para demonstrar:
 * - Herança (Pessoa -> Medico, Paciente)
 * - Encapsulamento (atributos privados + getters/setters)
 * - Construtores sobrecarregados
 * - Sobrescrita de métodos (toString)
 *
 * Classe de teste: Teste com método main cria médicos, pacientes e consultas.
 */
public class Teste {

    public static void main(String[] args) {
        // Criando especialidades
        Especialidade cardiologia = new Especialidade("Cardiologia", "CRM-CARD-01");
        Especialidade dermatologia = new Especialidade("Dermatologia", "CRM-DERM-02");

        // Criando planos de saúde
        PlanoSaude planoA = new PlanoSaude("VidaBem S/A", "12.345.678/0001-90", "Av. Central, 100", "11-4000-0000");
        PlanoSaude planoB = new PlanoSaude("SaudeFácil Ltda", "98.765.432/0001-11", "R. Saúde, 50", "11-5000-1111");

        // Criando médico com construtor completo
        Medico drFulano = new Medico("Dr. Fulano", "Rua das Flores, 10", "11-9999-0000", "CRM12345");
        drFulano.addEspecialidade(cardiologia);
        drFulano.addEspecialidade(dermatologia);
        drFulano.addConvenio(planoA);

        // Adicionando horários (segunda a sexta das 09:00 às 17:00)
        Horario horarioDia = new Horario(LocalTime.of(9, 0), LocalTime.of(17, 0));
        drFulano.addHorario(DayOfWeek.MONDAY, horarioDia);
        drFulano.addHorario(DayOfWeek.TUESDAY, horarioDia);
        drFulano.addHorario(DayOfWeek.WEDNESDAY, horarioDia);
        drFulano.addHorario(DayOfWeek.THURSDAY, horarioDia);
        drFulano.addHorario(DayOfWeek.FRIDAY, horarioDia);

        // Criando outro médico (sobrecarregando construtor)
        Medico draSicrana = new Medico("Dra. Sicrana", "Av. Saúde, 200", "11-9888-7777", "CRM54321");
        draSicrana.addEspecialidade(dermatologia);
        draSicrana.addConvenio(planoB);
        Horario periodoTarde = new Horario(LocalTime.of(13, 0), LocalTime.of(18, 0));
        draSicrana.addHorario(DayOfWeek.MONDAY, periodoTarde);
        draSicrana.addHorario(DayOfWeek.WEDNESDAY, periodoTarde);

        // Criando paciente com construtor simples (apenas nome e telefone)
        Paciente pacienteJoao = new Paciente("João Silva", "11-7777-6666");
        // Atualizando dados usando setters (simula cadastro posterior)
        pacienteJoao.setEndereco("R. dos Estudantes, 123");
        pacienteJoao.setDataNascimento(LocalDate.of(1985, 4, 20));
        pacienteJoao.setProfissao("Engenheiro");

        // Criando paciente com construtor completo
        Paciente pacienteMaria = new Paciente("Maria Oliveira", "11-6666-5555", LocalDate.of(1990, 8, 15), "R. Primavera, 45", "Professora");

        // Marcando consultas
        LocalDateTime dataHoraConsulta1 = LocalDateTime.of(2025, 10, 15, 10, 0); // 15/10/2025 10:00
        Consulta consulta1 = new Consulta(pacienteJoao, drFulano, dataHoraConsulta1, planoA); // com plano
        pacienteJoao.adicionarConsulta(consulta1);

        LocalDateTime dataHoraConsulta2 = LocalDateTime.of(2025, 10, 16, 14, 30);
        Consulta consulta2 = new Consulta(pacienteMaria, draSicrana, dataHoraConsulta2, null); // particular
        pacienteMaria.adicionarConsulta(consulta2);

        // Durante a consulta, médico registra observações
        consulta1.adicionarObservacao(new Observacao(ObservacaoTipo.QUEIXA, "Paciente refere dor no peito há 2 dias."));
        consulta1.adicionarObservacao(new Observacao(ObservacaoTipo.PRESCRICAO, "Solicitar ECG e prescrever AAS 100mg diário."));
        consulta1.adicionarObservacao(new Observacao(ObservacaoTipo.RESULTADO, "ECG com sinais de isquemia (a confirmar)."));

        consulta2.adicionarObservacao(new Observacao(ObservacaoTipo.QUEIXA, "Erupção cutânea no braço esquerdo."));
        consulta2.adicionarObservacao(new Observacao(ObservacaoTipo.PRESCRICAO, "Prescrever pomada anti-inflamatória e evitar exposição."));
        consulta2.adicionarObservacao(new Observacao(ObservacaoTipo.RESULTADO, "Melhora após 7 dias."));

        // Imprimindo dados para demonstração
        System.out.println("=== Médicos ===");
        System.out.println(drFulano);
        System.out.println(draSicrana);

        System.out.println("\n=== Pacientes ===");
        System.out.println(pacienteJoao);
        System.out.println(pacienteMaria);

        System.out.println("\n=== Consulta 1 (João com Dr. Fulano) ===");
        System.out.println(consulta1);
        System.out.println("Observações da consulta 1:");
        consulta1.listarObservacoes().forEach(System.out::println);

        System.out.println("\n=== Consulta 2 (Maria com Dra. Sicrana) ===");
        System.out.println(consulta2);
        consulta2.listarObservacoes().forEach(System.out::println);

        // Médico consulta observações anteriores que ele mesmo fez para o paciente
        System.out.println("\n=== Observações anteriores do Dr. Fulano para João ===");
        List<Observacao> historicoFulanoJoao = drFulano.consultarObservacoesAnteriores(pacienteJoao);
        historicoFulanoJoao.forEach(System.out::println);

        // Verificar disponibilidade de médico para um horário
        LocalDateTime tentativa = LocalDateTime.of(2025, 10, 15, 11, 0); // quarta-feira 11:00
        System.out.println("\nDr. Fulano disponível em " + tentativa + "? " + drFulano.isDisponivelEm(tentativa));
    }

    // --- CLASSES DO MODELO ---

    // Superclasse abstrata Pessoa (encapsulamento: atributos privados)
    static abstract class Pessoa {
        private String nome;
        private String endereco;
        private String telefone;

        public Pessoa(String nome) {
            this(nome, null, null);
        }

        public Pessoa(String nome, String endereco, String telefone) {
            this.nome = nome;
            this.endereco = endereco;
            this.telefone = telefone;
        }

        public String getNome() {
            return nome;
        }

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

        public String getEndereco() {
            return endereco;
        }

        public void setEndereco(String endereco) {
            this.endereco = endereco;
        }

        public String getTelefone() {
            return telefone;
        }

        public void setTelefone(String telefone) {
            this.telefone = telefone;
        }

        @Override
        public String toString() {
            return "Pessoa{nome='" + nome + "', endereco='" + endereco + "', telefone='" + telefone + "'}";
        }
    }

    // Especialidade
    static class Especialidade {
        private String nome;
        private String codigoCRM;

        public Especialidade(String nome, String codigoCRM) {
            this.nome = nome;
            this.codigoCRM = codigoCRM;
        }

        public String getNome() {
            return nome;
        }

        public String getCodigoCRM() {
            return codigoCRM;
        }

        @Override
        public String toString() {
            return "Especialidade{" + nome + " / " + codigoCRM + "}";
        }
    }

    // Plano de Saúde
    static class PlanoSaude {
        private String razaoSocial;
        private String cnpj;
        private String endereco;
        private String telefone;

        public PlanoSaude(String razaoSocial, String cnpj, String endereco, String telefone) {
            this.razaoSocial = razaoSocial;
            this.cnpj = cnpj;
            this.endereco = endereco;
            this.telefone = telefone;
        }

        public String getRazaoSocial() {
            return razaoSocial;
        }

        public String getCnpj() {
            return cnpj;
        }

        public String getEndereco() {
            return endereco;
        }

        public String getTelefone() {
            return telefone;
        }

        @Override
        public String toString() {
            return "PlanoSaude{" + razaoSocial + " / CNPJ:" + cnpj + "}";
        }
    }

    // Horário de atendimento
    static class Horario {
        private LocalTime inicio;
        private LocalTime fim;

        public Horario(LocalTime inicio, LocalTime fim) {
            if (inicio == null || fim == null) {
                throw new IllegalArgumentException("Inicio e fim não podem ser nulos.");
            }
            if (fim.isBefore(inicio) || fim.equals(inicio)) {
                throw new IllegalArgumentException("Fim deve ser depois do início.");
            }
            this.inicio = inicio;
            this.fim = fim;
        }

        public LocalTime getInicio() {
            return inicio;
        }

        public LocalTime getFim() {
            return fim;
        }

        public boolean contem(LocalTime hora) {
            return !hora.isBefore(inicio) && hora.isBefore(fim);
        }

        @Override
        public String toString() {
            return inicio + " - " + fim;
        }
    }

    // Médico (subclasse de Pessoa)
    static class Medico extends Pessoa {
        private String crm;
        private Map<DayOfWeek, Horario> horarios = new HashMap<>();
        private List<Especialidade> especialidades = new ArrayList<>();
        private List<PlanoSaude> convenios = new ArrayList<>();

        // Construtores sobrecarregados
        public Medico(String nome, String endereco, String telefone, String crm) {
            super(nome, endereco, telefone);
            this.crm = crm;
        }

        public Medico(String nome, String telefone, String crm) {
            super(nome, null, telefone);
            this.crm = crm;
        }

        public String getCrm() {
            return crm;
        }

        public void setCrm(String crm) {
            this.crm = crm;
        }

        public void addHorario(DayOfWeek dia, Horario horario) {
            horarios.put(dia, horario);
        }

        public void addEspecialidade(Especialidade esp) {
            if (esp != null) especialidades.add(esp);
        }

        public void addConvenio(PlanoSaude plano) {
            if (plano != null) convenios.add(plano);
        }

        public boolean isConveniadoCom(PlanoSaude plano) {
            return convenios.contains(plano);
        }

        public boolean isDisponivelEm(LocalDateTime dataHora) {
            Horario h = horarios.get(dataHora.getDayOfWeek());
            if (h == null) return false;
            return h.contem(dataHora.toLocalTime());
        }

        /**
         * Retorna todas as observações de consultas anteriores do paciente que foram
         * feitas por este mesmo médico.
         */
        public List<Observacao> consultarObservacoesAnteriores(Paciente paciente) {
            List<Observacao> resultado = new ArrayList<>();
            for (Consulta c : paciente.getConsultas()) {
                if (c.getMedico() == this) { // compara referência; se preferir, compare crm
                    resultado.addAll(c.getObservacoes());
                }
            }
            return resultado;
        }

        @Override
        public String toString() {
            return "Medico{" +
                    "nome='" + getNome() + '\'' +
                    ", crm='" + crm + '\'' +
                    ", telefone='" + getTelefone() + '\'' +
                    ", endereco='" + getEndereco() + '\'' +
                    ", especialidades=" + especialidades +
                    ", convenios=" + convenios +
                    ", horarios=" + horarios +
                    '}';
        }
    }

    // Paciente (subclasse de Pessoa)
    static class Paciente extends Pessoa {
        private LocalDate dataNascimento;
        private String profissao;
        private List<Consulta> consultas = new ArrayList<>();

        // Construtores sobrecarregados
        public Paciente(String nome, String telefone) {
            super(nome, null, telefone);
        }

        public Paciente(String nome, String telefone, LocalDate dataNascimento, String endereco, String profissao) {
            super(nome, endereco, telefone);
            this.dataNascimento = dataNascimento;
            this.profissao = profissao;
        }

        public LocalDate getDataNascimento() {
            return dataNascimento;
        }

        public void setDataNascimento(LocalDate dataNascimento) {
            this.dataNascimento = dataNascimento;
        }

        public String getProfissao() {
            return profissao;
        }

        public void setProfissao(String profissao) {
            this.profissao = profissao;
        }

        public void adicionarConsulta(Consulta consulta) {
            if (consulta != null) consultas.add(consulta);
        }

        public List<Consulta> getConsultas() {
            return Collections.unmodifiableList(consultas);
        }

        @Override
        public String toString() {
            return "Paciente{" +
                    "nome='" + getNome() + '\'' +
                    ", telefone='" + getTelefone() + '\'' +
                    ", endereco='" + getEndereco() + '\'' +
                    ", dataNascimento=" + dataNascimento +
                    ", profissao='" + profissao + '\'' +
                    '}';
        }
    }

    // Enum para tipos de observação
    enum ObservacaoTipo {
        QUEIXA,
        PRESCRICAO,
        RESULTADO
    }

    // Observação registrada numa consulta
    static class Observacao {
        private ObservacaoTipo tipo;
        private String texto;
        private LocalDateTime timestamp;

        public Observacao(ObservacaoTipo tipo, String texto) {
            this.tipo = tipo;
            this.texto = texto;
            this.timestamp = LocalDateTime.now();
        }

        public ObservacaoTipo getTipo() {
            return tipo;
        }

        public String getTexto() {
            return texto;
        }

        public LocalDateTime getTimestamp() {
            return timestamp;
        }

        @Override
        public String toString() {
            return "[" + timestamp + "] " + tipo + ": " + texto;
        }
    }

    // Consulta entre paciente e médico
    static class Consulta {
        private Paciente paciente;
        private Medico medico;
        private LocalDateTime dataHora;
        private PlanoSaude plano; // pode ser null (particular)
        private List<Observacao> observacoes = new ArrayList<>();

        public Consulta(Paciente paciente, Medico medico, LocalDateTime dataHora, PlanoSaude plano) {
            this.paciente = paciente;
            this.medico = medico;
            this.dataHora = dataHora;
            this.plano = plano;
        }

        public Paciente getPaciente() {
            return paciente;
        }

        public Medico getMedico() {
            return medico;
        }

        public LocalDateTime getDataHora() {
            return dataHora;
        }

        public PlanoSaude getPlano() {
            return plano;
        }

        public void adicionarObservacao(Observacao obs) {
            if (obs != null) observacoes.add(obs);
        }

        public List<Observacao> getObservacoes() {
            return Collections.unmodifiableList(observacoes);
        }

        public List<Observacao> listarObservacoes() {
            return getObservacoes();
        }

        public List<Observacao> obterObservacoesPorTipo(ObservacaoTipo tipo) {
            List<Observacao> res = new ArrayList<>();
            for (Observacao o : observacoes) {
                if (o.getTipo() == tipo) res.add(o);
            }
            return res;
        }

        @Override
        public String toString() {
            return "Consulta{" +
                    "paciente=" + paciente.getNome() +
                    ", medico=" + medico.getNome() +
                    ", dataHora=" + dataHora +
                    ", plano=" + (plano == null ? "Particular" : plano.getRazaoSocial()) +
                    '}';
        }
    }
}

Exercícios relacionados