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

Getters, Setters e "Encapsulamento"

Em exemplos de códigos de desenvolvedores tanto iniciantes quanto avançados, eu vejo isso acontecer:

class Ninja {
    private double chakra;
     public void setChakra(double chakra) {
        this.chakra = chakra;
    }
    public double getChakra() {
        return chakra;
    }
}

Faz sentido tornamos um membro privado e mesmo assim darmos acesso completo a ele? Não é melhor economizar código e fazer o código desta forma?

class Ninja {
    public double chakra;
}

Existe alguma diferença?

9 respostas

Existe diferença, quando você usa "public double chakra" irá permitir que seja feito acesso direto ao atributo, permitindo com que ele seja alterado diretamente sem utilizar métodos (gets e sets, por exemplo). Definindo "private double chakra", você estará protegendo o atributo chakra e garantindo que ele só poderá ser alterada/acessado através de métodos.

Espero ter ajudado.

Mas quando os métodos não tem nenhuma lógica de acesso. Simplesmente pegam e devolvem a variável sem fazer nada com ela, assim como deixei no exemplo, tem alguma diferença se o acesso é através de métodos ou não?

solução!

Oi Gabriel, tudo bem?

Quando temos atributos privados e criamos getters e setters a eles, sim, estamos fazendo o mesmo que deixá-los públicos. Afinal, todo mundo terá acesso e poderá alterar seu valor.

O que devemos evitar é de criá-los, já que eles vazam detalhes sobre a implementação da nossa classe além de obrigar clientes a conhecer detalhes sobre as regras de negócio.

Um exemplo clássico que usamos na Caelum:

class Conta { 
    private double saldo;

    public void setSaldo(double saldo) { 
        ...
    }
    public double getSaldo() {
        ...
    }
}

Como faríamos um depósito de R$ 100,00 a partir dessa classe conta? Precisamos somar 100 ao saldo atual da conta, certo?

Conta conta = new Conta();
double saldoAtual = conta.getSaldo();
conta.setSaldo(saldoAtual + 100);

O cliente deve saber que, para realizar um depósito, ele deve somar 100 ao saldo antigo. Esse é um detalhe que a conta (e somente ela) deveria saber, certo? Sinal de que quebramos o encapsulamento vazando isso aos clientes.

Podemos deixar nosso modelo rico, dando-lhe um método deposita:

class Conta { 
    private double saldo;

    public void deposita(double quantia) { 
        this.saldo += quantia;
    }
}

Como realizar um depósito agora?

Conta conta = new Conta();
conta.deposita(100);

Outro exemplo (Android):

Queremos pegar um nome em um ListView de nomes, como fazer?

String nome =
            (String) listaDeNomes.getAdapter().getItem(posicao);

Repare que nesse caso, precisamos saber que temos que acessar um Adapter para ter acesso ao item.

Como diz a Lei de Demeter devemos evitar esse encadeamento de métodos get, já que isso também expõe detalhes de implementação.

Na própria API do Android, temos uma alternativa:

String nome =
            (String) listaDeNomes.getItemAtPosition(posicao);

Beleza?

Evite criar métodos get/set para todos os atributos, apesar de estamos mal acostumados. O objetivo da OO é tenta mapear o mundo real no nosso código, portanto crie comportamentos reais para seus objetos.

Afinal, você não fala pro seu gerente setar o saldo da sua conta, não é mesmo? (:

Espero que tenha ficado claro, qualquer dúvida pode perguntar!

Abraços!

Gabriel deixar o atributo public é um risco, pois pode quebrar sua aplicação, quando definimos métodos público que acessam esses atributos é justamente para dar segurança a eles, pois no método podemos adicionar regras de negócio que evitam nossa aplicação de quebrar. Espero ter ajudado.

Gabriel, mais alguma dúvida?

Gabriel, espia só.

//classe conta com o método publico
public class Conta{

    public double saldo;

} 

public class TesteConta{

        public static void main(String[] args){
                // instanciando o objeto;
                Conta cc = new Conta();

                cc.saldo = 100;

                //note que eu alterei o saldo sem usar nenhuma regra
                // isso é possível porque o o atributo é publico        
        }
}

note que da forma que tá eu posso alterar o saldo sem nenhuma regra de negocio, mas o saldo não é dependente do deposito e do saque? então seria mas coerente eu proteger o saldo , mas se eu proteger o sado como eu vou ver meu saldo? é aí que entra o método getSaldo() onde ele retorna o saldo, porém voce não consegue alterar o valor dele através desse método. Para esse caso por motivo de segurança não se deve implementar o método setSaldo(). Deu pra entender Gabriel?

O mal dos programadores atuais é usar Getters e Setters para tudo. Não se deve usar getter e setter para todos os atributos, getters e setters são para encapsular regras de negócio, ou seja, você ver um método dirigir() você sabe o que ele faz, mais não sabe como ele funciona. Encapsular é isso! Não saiam jogando getters e setters para tudo, o rapaz foi bem em questionar.

Para mais informações e esclarecimentos de dúvidas segue um artigo da própria caelum sobre o assunto.

Como não aprender Java e orientação a objetos - Getters e Setters .

Bons estudos!

Obrigado Leonardo Cordeiro e os outros que também ajudaram. Minha duvida era porque quando ensinam orientação a objeto, sempre deixam os atributos privados mas criam getters e setters sem nenhuma lógica de acesso.

Beleza! Qualquer dúvida só mandar aqui no fórum.

Abraços a todos!