4
respostas

Beneficios da interface nesse caso.

Olá pessoal, em relação à interface eu fiquei com alguns questionamentos, vamos lá:

Desdo o começo o professou bateu na tecla de evitar repetir código por ficar mais difícil de fazer manutenção futuramente.

Nós temos as classes Gerente e Administrador que precisam de métodos de senha e autentica para acessarem um determinado sistema.

O gerente já possuía esses métodos, portanto para evitar ficar copiando código para o Administrador(assim como para tantos outros que pudessem vir a existir), criamos um outra classe FuncionarioAutenticavel com os métodos de senha e autentica.

FuncionarioAutenticavel herda Funcionário e por sua vez, Gerente e Administrador herdam FuncionarioAutenticavel. Dessa forma Gerente e Administrador está herdando os metodos de senha e autentica.

Aparentemente problema resolvido. Criamos uma 'subclasse' de funcionários que possuem métodos de senha, e que são Funcionarios também. Qualquer novo tipo de funcionário que precise de senha e que venha a existir é só fazer ele herdar o FuncionarioAutenticavel.

Agora um outro problema é que preciso que algum cliente também possua acesso ao sistema, ou seja, ele precisa ter os métodos de senha e autentica.Mas não posso faze-lo herdar FuncionarioAutenticavel, pois ele não é funcionário.

Então foi criado a interface Autenticavel com metodos abstratos. Agora Cliente, Gerente e Administrador 'assinam' esse contrato e precisam implementar cada um os metodos de senha e autentica.

Minha pergunta é: eu não poderia simplesmente copiar e colar os métodos de senha e autentica do Gerente para o Cliente e Administrador sem criar a interface? Eu sei que criando a interface parece que ganhamos em termos de deixar o código mais conciso, pois eu obrigo aquela classe a implementar tais métodos, que se caso não houvesse a interface alguma classe que precisa de senha iria ficar perdida.

Ma em termos de repitir código parece que não ganhamos tanto assim, pois como cada uma das classes vai ter que implementar os métodos, se por exemplo em quiser mudar a regra de setar a senha(tantos digitos p. ex) eu vou ter que faze essa alteração dentro de cada uma das classes que 'assinaram o contrato'.

É isso mesmo?

4 respostas

Oi José, tudo bem?

É exatamente isso. Como passamos a utilizar apenas a interface, teremos que implementar os métodos em todas as classes que assinaram o contrato de autenticação. Mas para resolver o problema da repetição de código, utilizamos a composição. Então, basicamente, usamos a interface para obrigar as classes a seguir o contrato e fazer uso das vantagens que o polimorfismo trás, enquanto isso a composição resolve os problemas de repetição de código que surgiram assim que substituímos a herança (extends) pela interface (implements).

Na próxima aula esse problema será solucionado, deixando claro o poder que a interface tem, principalmente se usado junto da composição! Inclusive, eu respondi um outro tópico falando um pouco mais sobre os dois, mas recomendo assistir a aula 7 antes para ter o contexto.

Assistindo a próxima aula, acredito que as coisas fiquem mais claras, mas se ficar qualquer dúvida estamos à disposição!

Bons estudos!!

Fala, Guilherme! Tudo bem contigo?

Eu entendo quando diz que em relação a escrita, sim! Vai ter que implementar um método para cada um, pois cada um terá um comportamento diferente, porém, se trabalharmos com Herança, como faremos se um novo Gerente for contratado e que não tenha os mesmo "comportamentos" do atual? Herdaremos os mesmos comportamentos do Funcionário.

Um artigo publicado em 01/08/2003 na Java World intitulado “Why extends is evil”, relata um comentário de James Goslin (criador do Java)

"Uma vez fui a uma reunião do grupo de usuários Java, onde James Gosling (inventor do Java) foi o orador de destaque. Durante o memorável Q&A sessão, alguém lhe perguntou: "Se você pudesse fazer Java novamente, o que você mudaria?" "Eu deixaria de fora as Classes", ele respondeu. Após sessarem os risos, ele explicou que o verdadeiro problema não era as Classes em si, mas sim a Herança de Implementação (extends). Herança de Interface (implements) é preferível. Você deve evitar a Herança de Implementação, sempre que possível. Why extends is evil — JavaWorld"

Temos um comentário do Emerson Torres sobre Interface que vale a leitura, Guilherme! Dê uma conferida lá!!!

Um abraço e bons estudos!

Qualquer dúvida, pode nos chamar ;-)

Essa é apenas uma base, imagine que você tenha uma empresa com 30 tipos de funcionários diferentes e cada tipo tem uma assinatura diferente de determinada interface. Pensando por esse lado, faz sentido achar que a interface não vai reutilizar código.

E você pode evitar repetir código através da composição, isso somente quando tiver tipos com implementações iguais, aí por exemplo, 4 tipos implementam a mesma coisa, basta utilizar a composição para não ter a mesma implementação de código nesses 4 tipos (suponhamos que a implementação seja gigante), a implementação gigante fica apenas na classe de composição.

Obrigado pelas respostas pessoal.

Eu refiz o código todo para fixar melhor os conceitos. Mas agora pensei em algo novo.

Eu quis criar um novo sistema no qual apenas o Gerente tem acesso. Fiz as seguintes Alteraçoes:

-Criei a classe SistemaExterno, e a interface AutenticavelExterno (Cliente,Adm e Gerentes assinam esse contrato)

public class SistemaExterno {

    public void autentica(AutenticavelExterno a, int senha) {
        boolean autenticou = a.autenticaExterno(senha);
        if (autenticou) {
            System.out.println("Pode entrar no sistema");
        } else {
            System.out.println("Não pode entrar no sistema");
        }
    }
}

public abstract interface AutenticavelExterno {

    public abstract void setSenhaExterna(int senha);

    public abstract int getSenhaExterna();

    public abstract boolean autenticaExterno(int senha);
}
  • Agora eu quero que os Gerentes tenham acesso a um outro sistema, a classe SistemaGerencial. Mas para funcionar preciso que a autenticação receba apenas pessoas do tipo gerente. E a senha deve ser diferente. Então criai a interface AutenticavelGerente.
public class SistemaGerencial {

    public void autentica(AutenticavelGerente a, int senha) {
        boolean autenticou = a.autenticaGerente(senha);
        if (autenticou) {
            System.out.println("Pode entrar no sistema");
        } else {
            System.out.println("Não pode entrar no sistema");
        }
    }
}

public abstract interface AutenticavelGerente {

    public abstract void setSenhaGerente(int senha);

    public abstract int getSenhaGerente();

    public abstract boolean autenticaGerente(int senha);
}

-Agora o Gerente possui acesso aos dois sistemas e tem duas senhas:

public class Gerente extends Funcionario implements AutenticavelExterno, AutenticavelGerente{

    private int senhaExterna;
    private int senhaGerente;

       //getters e setters

É mais ou menos por ai ou da pra melhorar com o lance da composição?

Outra duvida, o autentica do sistema está recebendo uma referência para um objeto, no caso do SistemaGerencial está recebendo uma referência para um tipo AutenticavelGerente.

Eu queria que ele recebesse a matrícula do funcionário e sua senha, e dessa matrícula identificar que ele é um AutenticavelGerente. Dá pra fazer isso, ou é assunto para cursos posteriores?