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

Acessar o nome do Funcionário/Cliente na Class SistemaInterno

Minha dúvida é simples, hoje o código para a Classe SistemaInterno é o seguinte.

public class SistemaInterno{

    private int senha = 2222;

    public void autentica(Autenticavel aut) {

        if (aut.autentica(this.senha))
            System.out.println("Pode entrar no sistema");
        else
            System.out.println("Não pode entrar no sistema");
    }
}

Caso eu quisesse que o código na verdade fosse algo do tipo

public class SistemaInterno {

    private int senha = 2222;

    public void autentica(Autenticavel aut,String nome) {

        if (aut.autentica(this.senha))
            System.out.println(nome + " pode entrar no sistema");
        else
            System.out.println(nome + " não pode entrar no sistema");
    }
}

Quando eu chamasse este metodo eu teria que fazer algo do tipo

        Administrador a1 = new Administrador();
        a1.setNome("Gabriel");
        si.autentica(a1, a1.getNome());

Entetanto isso me força a usar o getNome, essa seria a forma mais usual de se fazer OU vocês possuem alguma ideia que eu consiga fazer isso de forma mais generica de forma que eu só precisasse passar um Autenticavel como paramero?

Sei que isso depende muito de como a estrutura do meu código foi montada, mas usando como base o curso de Java sobre Interfaces e Classes Abstratas, vocês simplesmente passarião da forma que eu fiz ou farião algum outro esquema nas classes Cliente/Funcionario?

6 respostas

Fala Gabriel, tudo bem ?

O problema dessa solução justamente é que ela obriga quem escreve a classe que executa (a que usa a classe SistemaInterno) a chamar getNome e passar mais uma String para o método que autentica. Imagina se passarmos qualquer outra String, por exemplo, si.autentica(a1, a1.getSenha()); =/ vai dar ruim. Esse problema é exatamente o que também queríamos resolver com o uso da Interface e Polimorfismo.

Ao passar o Autenticavel para o método autentica, abrimos possibilidade de nos referirmos a qualquer que seja o autenticavel, e o método autentica pode ter segurança de chamar as operações certas do Autenticavel.

Uma alternativa a essa implementação pode vir de um pensamento mais conceitual. Se nessa linha (System.out.println(nome + " pode entrar no sistema")) estamos julgando que o autenticável deve ter nome, podemos então representar que todos eles terão essa característica. E onde definimos o contrato que define as características que todo autenticável deve ter ? -> na interface Autenticavel. =)

Poderíamos fazer algo assim:

public interface Autenticavel {
    int getSenha();
    String getNome();
}
public class Administrador implements Autenticavel {

    // obrigado a ter a  implementação de getNome e getSenha
    // e provavelmente terá os setters ou uma operação de construção com as duas informações
}

E assim o código do sistema interno pode ficar como o que segue:

public class SistemaInterno {

    private int senha = 2222;

    public void autentica(Autenticavel aut) {

        if (aut.getSenha() == senha)
            System.out.println(aut.getNome() + " pode entrar no sistema");
        else
            System.out.println(aut.getNome() + " não pode entrar no sistema");
    }
}
Administrador a1 = new Administrador();
a1.setNome("Gabriel");
a1.setSenha(2222);

si.autentica(a1);

Espero ter ajudado. Abraço!

Entendo seu ponto Rafael, mas temos um problema nisso.

A Classe Cliente e as Classes que herdam a classe Funcionario já possuem um metodo getNome.

Portanto entraria em conflito. Por isso havia pensado na ideia de passar a String com o nome, mas não me agradadou, justamente porque pode ser passado qualquer coisa.

Não que seja um problema como citei acima, mas seria só por questão de manter o "padrão" de nomenclatura, minha ideia então foi a seguinte

Na Interface Autenticavel

public abstract interface Autenticavel {
    String getNomeAut();

    void setSenha(int senha);

     boolean autentica(int senha);
}

E nas classes que implementão o Autenticavel algo do tipo

@Override
    public String getNomeAut() {
        return super.getNome();
    }

No caso de quem herda da classe abstrata Funcionario e para a Class Cliente:

@Override
    public String getNomeAut() {
        return this.getNome();
    }

Estou seguindo a idéia correta? Pois estou tentando evitar o maximo de repetir codigos, caso haja formas de melhorar isso me avise por favor!

Dessa forma ficaria assim o codigo final

public class SistemaInterno {

    private int senha = 2222;

    public void autentica(Autenticavel aut) {

        if (aut.autentica(this.senha))
            System.out.println(aut.getNomeAut() + " pode entrar no sistema");
        else
            System.out.println(aut.getNomeAut() + " não pode entrar no sistema");
    }
}
solução!

Fala Gabriel

Lembre-se que os métodos nas interfaces são todos abstratos, logo não existe conflito. Se sua classe que implementa a interface já tiver o método getNome() simplesmente o Java entende que a classe já está cumprindo com o contrato que a interface o obriga. A ideia do uso de interfaces é justamente essa, evitar qualquer questão conflitante.

Exemplo:

Já tenho uma classe Gerente que tem nome, salario e senha e seus respectivos getters and setters implementados.

public class Gerente {
    private String nome;
    private BigDecimal salario;
    private String senha;

    // getters and setters
}

Se eu crio uma interface hoje que obrigue quem seguir seu contrato a ter getSenha e getNome...

public interface Autenticavel {
    String getSenha();
    String getNome();
}

... e depois faço o Gerente implementar essa interface com public class Gerente implements Autenticavel, não tenho problema de conflito. Tudo funciona, dado que Gerente já cumpre com as obrigações mesmo antes do vínculo com a interface.

De mesma forma, posso ainda fazer a classe implementar alguma outra interface que tenha a mesma obrigação contratual (ou parte dela). Exemplo:

public interface Bonificavel {
    String getNome();
}

E se implementar também essa interface -> public class Gerente implements Autenticavel, Bonificavel não existe nenhum conflito, pois apenas com uma implementação de getNome() (que já existia mesmo antes das interfaces) já estou seguindo o comportamento exigido pelos dois contratos das interfaces.

Abraço!

Otimá explicação Rafael, de verdade, ficou bem claro agora.

Eu acreditava que para ele entender que o getNome() pertencia a classe abstrata eu precisaria colocar o @Override por cima, mas mesmo não colocando ele se comportou exatamente como você falou.

Muito obrigado mesmo!

Rafael, marquei a resposta errada como solução... se conseguir alterar para colocar a sua resposta como solução, agradeço, pois não achei aonde mudo isso.

Alterei por aqui Gabriel. Valeu!

Abraço e bons estudos.