Solucionado (ver solução)
Solucionado
(ver solução)
6
respostas

Ex. 3 - Aula 6 - Construtores: Como repetir a função, caso o argumento seja inválido?

Pessoal... O exercício 3 da aula 6 pede para que o programa sinalize que a data informada é inválida... Entendi como fazer isso.

Porém, caso eu queira informar que é inválida e logo em seguida chamar o mesmo método automaticamente, para que o usuário informe um argumento válido, como eu poderia fazer? Código da dúvida está na class Data.

Segue o código atual:

class Empresa{

  private String nome;
  private String cnpj;
  private Funcionario[] empregados;
  private int livre = 0;
  private int tamanhoArray;

  public Empresa(int tamanhoArray){
    this.empregados = new Funcionario[tamanhoArray];
  }

  public void adiciona(Funcionario f) {
    this.empregados[this.livre] = f;
    this.livre++;
  }

//  ADICIONA ALTERNATIVO
//  void adiciona(Funcionario f){
//    for(int i=0; i<empregados.length; i++){
//      if(this.empregados[i] == null){
//        this.empregados[i] = f;
//        break;
//      }
//    }
//  }


  //ok
  void getNomeEmpregados(){
    for(int i=0; i<this.livre; i++){
      if(empregados[i] != null){
        System.out.println("Posição " + i + ": " + empregados[i].getNome());
      }
    }
  }

  //ok
  void getTodasAsInformacoes(){
    for(int i=0; i<this.livre; i++){
      if(empregados[i] == null)
        continue;
      System.out.println("Posição " + i + ":");
      this.empregados[i].mostra();
    }
  }

  //ok
  boolean contem(Funcionario f){
    for(int i=0; i<this.livre; i++){
      if(f == this.empregados[i]){
        return true;
      }
    }
    return false;
  }

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

  //ok
  public String getNome(){
    return this.nome;
  }

  //ok
  public void setCnpj(String cnpj){
    this.cnpj = cnpj;
  }

  //ok
  public String getCnpj(){
    return this.cnpj;
  }

  public void setEmpregados(Funcionario[] empregados){
    this.empregados = empregados;
  }

  //ok
  public Funcionario getEmpregados(int posicao){
    return this.empregados[posicao];
  }

  public int getArrayLength(){
    return this.empregados.length;
  }


}
class Funcionario{
  private String nome;
  private String departamento;
  private double salario;
  private Data dataEntrada;
  private String rg;

  Funcionario(){
  }

  Funcionario(String nome){
    this.nome = nome;
  }


  //ok
  public void setAumento(double valor){
    System.out.println("Antigo salário: " + this.salario);
    this.salario += valor;
    System.out.println("Novo salário: " + this.salario + "\n");
  }

  //ok
  public double getGanhoAnual(){
    return this.salario * 12;
  }

  //ok
  public void mostra(){
    System.out.println("Nome: " + this.getNome());
    System.out.println("Departamento: " + this.getDepartamento());
    System.out.println("Salário: " + this.getSalario());
    System.out.println("Entrada: " + this.getDataEntrada());
    System.out.println("RG: " + this.getRg() + "\n");
  }

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

  //ok
  public double getSalario(){
    return this.salario;
  }

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

  //ok
  public String getNome(){
    return this.nome;
  }

  //ok
  public void setDepartamento(String departamento){
    this.departamento = departamento;
  }

  //ok
  public String getDepartamento(){
    return this.departamento;
  }

  //ok
  public void setDataEntrada(Data dataEntrada){
    this.dataEntrada = dataEntrada;
  }

  //ok
  public String getDataEntrada(){
    if(this.dataEntrada.dia == 0 || this.dataEntrada.mes == 0 || this.dataEntrada.ano == 0){
      return "Data não informada";
    }else{
    return this.dataEntrada.getFormatada();
    }
  }

  //ok
  public void setRg(String rg){
    this.rg = rg;
  }

  //ok
  public String getRg(){
    return this.rg;
  }
}
class Data{
  int dia;
  int mes;
  int ano;

  void preencheData(int dia, int mes, int ano){
    this.dia = dia;
    this.mes = mes;
    this.ano = ano;

    if (! isDataViavel(dia, mes, ano)){
      System.out.println("A data " + getFormatada() + " é inválida.");
    }
  }




  private boolean isDataViavel(int dia, int mes, int ano){
    if (dia < 1 || mes < 1 || mes > 12 || ano < 1){
      return false;
    }

    int ultimoDiaDoMes = 31;
    if(mes == 4 || mes == 6 || mes == 9 || mes == 11){
      ultimoDiaDoMes = 30;
    }else if(mes == 2){
      ultimoDiaDoMes = 28;
      if((ano % 400 == 0) || ((ano % 4 == 0) && (ano % 100 != 0))){
        ultimoDiaDoMes = 29;
      }
    }
    if (dia > ultimoDiaDoMes){
      return false;
    }

    return true;
  }




  String getFormatada(){
    return this.dia + "/" + this.mes + "/" + this.ano;
  }
}
class TestaEmpresa{
  public static void main(String[] args){

    Funcionario lucas = new Funcionario();
    lucas.setNome("Lucas");
    lucas.setDepartamento("Coordenação de TI");
    lucas.setSalario(1000);
    lucas.setRg("11.111.111");
    Data d1 = new Data();
    d1.preencheData(1, 11, 1111);
    lucas.setDataEntrada(d1);

    Funcionario isadora = new Funcionario();
    isadora.setNome("Isadora");
    isadora.setDepartamento("Coordenação de RH");
    isadora.setSalario(2000);
    isadora.setRg("22.222.222");
    Data d2 = new Data();
    d2.preencheData(2, 22, 2222);
    isadora.setDataEntrada(d2);

    Funcionario renato = new Funcionario();
    renato.setNome("Renato");
    renato.setDepartamento("Coordenação de Compras");
    renato.setSalario(3000);
    renato.setRg("33.333.333");
    Data d3 = new Data();
    d3.preencheData(3, 33, 3333);
    renato.setDataEntrada(d3);

    Empresa empresa = new Empresa(12);
    //Funcionario[] empregados = new Funcionario[10];
    //empresa.setEmpregados(empregados);

    empresa.adiciona(lucas);
    empresa.adiciona(isadora);
    //empresa.adiciona(renato);



    /////TESTES INICIO///

    //empresa.getEmpregados();

    //empresa.getTodasAsInformacoes();

    //System.out.println(empresa.contem(lucas));
    //System.out.println(empresa.contem(renato)); //REMOVER RENATO DA EMPRESA[] QUANDO FOR REALIZAR TESTE


//    empresa.setNome("AAA");
//    empresa.setCnpj("BBB");
//    System.out.println(empresa.getNome());
//    System.out.println(empresa.getCnpj());

//    System.out.println(empresa.getEmpregados(1).getNome());

//    System.out.println(empresa.getArrayLength());
  }
}
class TestaFuncionario{

  public static void main(String[] args){

    Funcionario lucas = new Funcionario();
    lucas.setNome("Lucas");
    lucas.setDepartamento("Coordenação de TI");
    lucas.setSalario(1000);
    lucas.setRg("11.111.111");
    Data d1 = new Data();
    d1.preencheData(1, 11, 1111);
    lucas.setDataEntrada(d1);

    Funcionario isadora = new Funcionario();
    isadora.setNome("Isadora");
    isadora.setDepartamento("Coordenação de RH");
    isadora.setSalario(2000);
    isadora.setRg("22.222.222");
    Data d2 = new Data();
    d2.preencheData(2, 22, 2222);
    isadora.setDataEntrada(d2);

    Funcionario renato = new Funcionario();
    renato.setNome("Renato");
    renato.setDepartamento("Coordenação de Compras");
    renato.setSalario(3000);
    renato.setRg("33.333.333");
    Data d3 = new Data();
    d3.preencheData(3, 33, 3333);
    renato.setDataEntrada(d3);

    /////TESTES INICIO//////

//    System.out.println(lucas.getNome());
//    System.out.println(lucas.getDepartamento());
//    System.out.println(lucas.getSalario());
//    System.out.println(lucas.getRg());
//    System.out.println(lucas.getDataEntrada());
//    System.out.println(lucas.getGanhoAnual());

//    lucas.mostra();

//    System.out.println(lucas.getSalario());
//    lucas.setAumento(1000);
//    System.out.println(lucas.getSalario());

    /////TESTES FIM/////


  }
}
6 respostas

Troquei "método" por "função" no título da dúvida.

Você pode chamar o método novamente, dentro dele mesmo.

solução!

Olá Lucas,

Aqui, na classe TestaFuncionario e TestaEmpresa estamos testando nosso código e estamos inserindo os valores "na mão" ou "hard coded". Isso significa que você programador está inserindo na linha do código um dado que vai ser sempre o mesmo toda vez que você executar o programa. Entende?

Então essa ideia de chamar o método de novo caso a Data seja inválida é quando já temos algum tipo de interação com o usuário em tempo de execução do programa. É um passo a mais do que estamos querendo fazer aqui. É quando já temos formas de pegar dados que o usuário digita e usarmos dentro do programa. O Scanner por exemplo, é uma classe que ajuda a fazer isso. (https://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html)

Mas adiantando um pouco agora, o que poderíamos fazer então, é definir um retorno boolean para o método preencheData(). Se conseguiu preencher, retorna "true" e se não conseguiu, retorna "false".

IMPORTANTE

Lembre-se de que a ordem de execução dos comandos é linear: de cima para baixo. Da forma como você colocou, sempre estamos inserindo os dados, antes de checar se eles são válidos! Veja como poderia ficar se invertermos a ordem:

boolean preencheData(int dia, int mes, int ano){
     if (!isDataViavel(dia, mes, ano)){
        System.out.println("A data " + getFormatada() + " é inválida.");
        return false;
    }
    this.dia = dia;
    this.mes = mes;
    this.ano = ano;
    return true;
  }

Assim, garantimos que só inserimos a Data se ela for válida, pois se não for, o método termina de executar retornando "false".

Lembrando que caso o método seja void, você também pode escrever apenas return; para finalizar a execução do método.

Gabriel,

Tome cuidado, chamar o método dentro dele mesmo pode ser perigoso!

É algo que "funciona" porque estamos pensando em que o usuário vai errar algumas vezes e inserir os dados corretos eventualmente. Mas desse jeito, estamos deixando o sistema vulnerável a estourar a memória.A cada vez que você chama um método, ele fica guardado em memória até que seja terminado. E caso você chame um método dentro do outro, eles são guardados de forma encadeada, numa pilha. Só libera o método chamado primeiro depois que o segundo já terminou. Ou seja, se fizermos assim,

boolean preencheData(int dia, int mes, int ano){
     if (!isDataViavel(dia, mes, ano)){
        System.out.println("A data " + getFormatada() + " é inválida.");
        preencheData(-1, -1, -1);
    }
    ...
  }

OU deixarmos a chance do usuário (principalmente os mal-intencionados) poderem inserir milhares de vezes a informação errada, estaremos guardando na memória as chamadas de métodos até não haver espaço e estourar.

A sugestão que dei acima evita isso, pois terminamos a chamada do método a cada tentativa do usuário.

Bom saber Lucas, obrigado!

Obrigado, Lucas!