Esclarecendo o encapsulamento

Galera, andei refletindo sobre a utilização do encapsulamento e fiquei meio confuso sobres o assunto. Sera que alguém pode me dizer se sou obrigado a utilizar os métodos get e set em todos os atributos, e se a não utilização deles é um mau habito de programação?


É errado pensar que o uso de get/set ( formalmente, metodos acessores e modificadores, respetivamente) é errado. Não é errado.
Java é orientado a objetos e um objeto com atributos publicos não é uma objeto é uma imitação de um struts do C.

Por definição de objeto, todo e qualquer estado é privado. Nunca jamais os atributos de uma objeto devem ser outra coisa que não private. Nem sequer protected.
Quer acessar o estado ? pergunta ao objeto. Pode ser que ele responde o que tem no seu atributo, pode ser que não. Vc nunca saberá . É private!

Em programação OO é muito comum precisar do padrão PropertyBag. E em java , isso é feito com um map ou com um objeto simples com privates e um get/set para cada um. É um padrão ! use. muitos frameworks se utilizam desse padrão. Não é errado.

Em C# é a mesma coisa. A sintaxe é diferente, o compilador até cria os privates sozinho , mas é o mesmo padrão. A mesma coisas em groovy por exemplo. E muitas outras linguagens. O padrão PropertyBag é muito usado, então as linguagens tem que decidir como irão dar suporte a ele. Java escolher o caminho mais cru. Sem magia. O C# escolher o caminho com o conceito de Property.

Vc não é obrigado a usar o padrão PropertyBag. Vc pode usar estrutruas ( todos os atributos publicos, sem get/set). Em certos pontos issot é util, mas em API publicas não.

Também é errado pensar que vc irá colocar algum codigo “de validação” no set. Isso não existe. É um artificio usados nas escolas, mas no mundo real não é assim que se faz.

Agora, isto é tudo bonito quando vc está usando propertyBag (entidades, DTO, são deste padrão). Mas é errado em serviços, por exemplo. Mas é errado porque não faz sentido, não porque viola um padrão ou uma regra.
Não faz sentido porque se oserviço A depende de B, A não pode ser criado sem acesso a B, logo, B deve ser pssado no contrutor e nao num set. O spring obrigou este padrão de serviços com propriedades (ele não obriga, as pessoas que usam assim). Isto que é perigoso porque viola a inversão de dependencia. Apenas serviços opcionais devem ser anexados via setter.

Em geral nenhum objeto que não seja um propertyBag precisa de get/set. Não ah nada de errado com get/set em si, são os usos errados deles em relação à responsabilidade do objeto que são errados.

No final, o compilador vai fazer inline disso tudo e tudo acontece como se vc estivesse usando o atributo como publico. Mas em termos de design, se o atributo é publico , está errado.

Se como alternativa, você vai acessar os atributos diretamente (fazendo atributos públicos), é um mal hábito não usar getters e setters.

Se você não criou o setter e/ou getter para determinado atributo. Não é um mal hábito.

Então, você não é obrigado a criar. Porém, não pode acessar os atributos diretamente.

Imagine que você tenha um atributo dentro de uma classe qualquer, mas que não queira que ele seja alterado diretamente, qual recurso utilizar? Através de métodos específicos. E o que eles tem haver com as ?boas práticas?? Com essa ideia deles aplica-se uma regra da orientação a objeto chamada encapsulamento que consiste que os atributos de uma classe não possam ser acessados diretamente, com isso você também tem mais controle sobre seus atributos, com eles evita-se que outras classes possam alterar valores das variáveis sem o controle da própria classe, e deixa o código mais ?limpo?.
O padrão utilizado nessa manipulação dos atributos são os métodos set e get. O método set é usado para definir um valor para o atributo e o método get para recuperar o valor do atributo.
A seguir a sintaxe dos dois métodos:

public class Funcionario { private String nome; private double salario; }

Primeira observação: Porque o modificar tem que ser private? A resposta é óbvia, se você quer que seus atributos não sejam alterados diretamente, que sentido faz declara-los como public? Nenhum!
Declaramos nossas variáveis, vamos começar a usar os métodos:

[code]public class Funcionario
{
private String nome;
private double salario;

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

public String getNome()
{
	return nome;
}

}[/code]

Vamos analisar o método set primeiro: Usa-se void pois ele não retorna valor algum, ele apenas atribui/modifica. E a palavra this serve para diferenciar o atributo da classe do parâmetro que será passado. Se você não passar esse parâmetro, não terá como você atribuir/modificar seu atributo.
Método get: Foi construído com uma String (Já que o atributo usado é uma String) ele tem que retornar algo, o void não retorna valor algum. Como dito na definição, o get recupera um valor, para isso usa-se o return.

Agora que já construímos nossos setters e getters, podemos testa-los:

[code]public class Teste
{
public static void main(String[] args)
{
Funcionario a = new Funcionario();

	a.setNome("Leandro Almeida");
	a.setSalario(699.39);

	System.out.println("Funcionário: "+a.getNome()+"\nSalário: "+a.getSalario());
}

}[/code]

Análise do código acima:

Para que se possa atribuir valores e recuperar, antes você tem que instanciar algum objeto. Se for tentar colocar dentro do Main somente ?setNome(?Leandro Almeida?);? não irá funcionar, pois você não está dizendo qual objeto quer atribuir! Precisamos declarar e instanciar um objeto da classe Funcionário para poder usar seus métodos!
O mesmo serve para o getNome e getSalario, você tem que dizer para o método qual valor do objeto será recuperado.
Esses métodos são interessantes quando sabe-se usa-los, pois se não, você acaba sem querer de romper essa regra de ?boas práticas? na programação, não é necessário que em todo atributo você construa um setter e um getter para ele, somente quando realmente for necessário.	

Está tudo aí, fiz esse resumo esses dias aqui no estágio. (=

Opa! Valeu pelas respostas gente, e desculpa demorar responder, estava com problemas no meu PC aqui em casa. Mas é isso ai, vou continuar lendo algumas coisas sobre padroes de projetos e logo logo to craque! :lol:

Abraço!