Eu ainda não entendo o por que dos getters e setters?

:shock: Olá Senhores,

Fiz essa pergunta na última aula que tive de LOO1 e o professor rodou, rodou mas não respondeu… talvez vocês possam me explicar algo além do que ele disse “é design pattern, encapsulamento, tem que seguir as normas…”

Não sei se ele não respondeu por não saber mais técnicamente ou talvez porque não quis responder mesmo, mas ainda assim a dúvida continua, sei que é design pattern, até mesmo no eclipse tem uma opção para gerar automaticamente os getters e setters da class… mas técnicamente falando, porque criamos 2 metodos para trabalhar com cada variável se poderiamos atribuir e pegar o valor delas diretamente por um nomeobj.Variavel sendo ela public???

Abraços.

  1. Nao, nao eh um design pattern.

  2. Encapsulamento.

Rafael

[quote=Rafael Steil]1) Nao, nao eh um design pattern.

  1. Encapsulamento.

Rafael[/quote]

É, vc já pode dar aula em faculdade *rs :smiley: !
Brincadeiras a parte talvez eu deva procurar saber o que é encapsulamento 1º :cry:

Os getters e setters sao adotados como um padrao pra acesso aos atributos de uma classe…

Nao é bom voce ter acesso diretamente ao atributo na maioria dos casos…

Um exemplo bem simples seria não permitir valores indesejados…

Caso voce tenha um atributo idade por exemplo, voce nao gostaria que esse valor fosse negativo… o setter pode resolver esse problema…

Usar get/set serve para restringir o acesso aos atributos, uma das características do encapsulamento. Infelizmente, vais ter que acreditar que é “melhor assim”, como disseram. Pelo menos até que entendas por conta própria, ao mexer com código suficientemente complexo.

Mas meu sexto sentido indica que tua reclamação é um pouco diferente, em relação ao excesso de classes nas quais cada atributo tem seus respectivos setter e getter, e nenhum comportamento mais elaborado.

Bem, nesse caso, o problema é mais embaixo: http://fragmental.com.br/wiki/index.php?title=Evitando_VOs_e_BOs .

Digamos que você tenha uma classe com os atributos:

Nome, Idade e Saldo.

É sempre desejável que a classe sempre esteja válida, isto é, com os atributos sempre válidos. Para isso ao invés de permitir que o programador mande qualquer valor para os atributos, limita-se o acesso a eles por métodos, que fazem uma checagem dos dados antes de modificar os atributos.

Outra utilidade é para se fazer atributos “somente leitura”, disponibilizando só o getter.

Normalmente se coloca setters e getters em tudo, pois pode ser que no final do seu projeto você perceba que tem que validar certo atributo, o que vai ser bem mais fácil de fazer acrecentando uma linha de código do que ter que mudar todas as classes que o acessavam diretamente =)

getters e setters são uma gambiarra aceita como padronização de encapsulamento de campos em java para contornar a falta de algo como a palavra reservada property do object pascal, que escondia do usuário se o acesso estava sendo feito diretamente a um campo ou a um metodo …

estão pensando sériamente em resolver isto para o java 7 :smiley:

Você também pode criar mais um setter/getter para o mesmo atributo, quando isso for conveniente.

Por exemplo, na classe

public class Quadrado { private int x; private int y; private int largura; private int altura;

Podemos ter os seguintes sets:
void setX(int x)
void setY(int y)
void getAltura(int altura);
void getLargura(int largura);
void setTop(Point top);
void setBounds(Point topLeft, Point bottomRight);
void setSize(int largura, int altura);

E assim por diante… Note que embora sejam sets diferentes, lidam sobre os mesmos atributos…

Outra coisa é que você pode ter mais de uma ação dentro de um set.

Por exemplo:

[code]public class Jogador {
private int vidas;

public void setVida(int vidas) {
vidas–;
if (vidas == 0) {
morrer();
}
}
[/code]

Você pode ter atributos read-only. Ou seja, só com get e sem set.

Finalmente, alguns atributos devem ser mudados apenas por sua classe, sem usar o método set. Um set pode ser uma quebra de encapsulamento se comprometer o estado de sua classe. Veja por exemplo a classe abaixo:

[code]public class Semaforo {
private Color cor;

public void mudarDeCor() {
if (cor == Color.RED)
cor = Color.GREEN;
else if (cor == Color.YELLOW)
cor = Color.RED;
else if (cor == Color.GREEN)
cor = Color.YELLOW;
}

public Color getCor() {
return cor;
}
}[/code]

Note que um set aqui só atrapalharia. Você poderia fazer o semáforo passar de verde diretamente para vermelho. O mesmo aconteceria se você tivesse atributos públicos.

[quote=urubatan]getters e setters são uma gambiarra aceita como padronização de encapsulamento de campos em java para contornar a falta de algo como a palavra reservada property do object pascal, que escondia do usuário se o acesso estava sendo feito diretamente a um campo ou a um metodo …

estão pensando sériamente em resolver isto para o java 7 :D[/quote]

Isso realmente seria muito útil.
Deixaria o código mais limpo, com certeza.

vc declarar uma variavel como publica taria quebrando o encapsulando e os conceitos de uma boa OO. Bom get e set é apenas uma nomeacao java beans… vc pode usar o que quiser nos seus metodos… mais a nomeação java beans eh usada por 99% dos programadores java…(nao se outras linguagues OO implementa esse conceito) uma variavel como publica vc nao precisa ter metodos set e get ja que pode acessar ela de qualquer class dentro ou fora do pacote ja que eh publica…
o uso de set e get eh para forçar que o acesso as variaveis sejam apenas por eles desde que elas sejam privadas…

[quote=tiagomac] :shock: Olá Senhores,

Fiz essa pergunta na última aula que tive de LOO1 e o professor rodou, rodou mas não respondeu… talvez vocês possam me explicar algo além do que ele disse “é design pattern, encapsulamento, tem que seguir as normas…”

Não sei se ele não respondeu por não saber mais técnicamente ou talvez porque não quis responder mesmo, mas ainda assim a dúvida continua, sei que é design pattern, até mesmo no eclipse tem uma opção para gerar automaticamente os getters e setters da class… mas técnicamente falando, porque criamos 2 metodos para trabalhar com cada variável se poderiamos atribuir e pegar o valor delas diretamente por um nomeobj.Variavel sendo ela public???

Abraços.

[/quote]
Na época que IDE era luxo de quem podia pagar, os getters e setters eram utilizados para aumentar o prazo do projeto e encher nosso saco de ficar digitando get e set o dia inteiro.

[quote=tiagomac] :shock: Olá Senhores,

Fiz essa pergunta na última aula que tive de LOO1 e o professor rodou, rodou mas não respondeu… talvez vocês possam me explicar algo além do que ele disse “é design pattern, encapsulamento, tem que seguir as normas…”

Não sei se ele não respondeu por não saber mais técnicamente ou talvez porque não quis responder mesmo, mas ainda assim a dúvida continua, sei que é design pattern, até mesmo no eclipse tem uma opção para gerar automaticamente os getters e setters da class… mas técnicamente falando, porque criamos 2 metodos para trabalhar com cada variável se poderiamos atribuir e pegar o valor delas diretamente por um nomeobj.Variavel sendo ela public???

Abraços.

[/quote]

Vc poderia escrever uma classe assim :


public class Pessoa{

      public XDate nascimento;

}

E usar assim:


Pessoa x = new Pessoa ();
x.nascimento= new XDate(1956,5,17); // XDate é uma classe fictica

O Java deixa vc fazer isso. vc não é obrigado a usar get e set
Mas ao não usar get e set vc está criando problemas para si mesmo porque não está encapsulando o estado do objeto. É aqui que entram considerações mais importantes que simples codificação.
O principio do encapsulamento afirma que ninguém pode aceder ao estado de um objeto exceto ele próprio.
Isso significa que teremos que criar métodos no objecto para que outros objectos obtenham os dados e tornar o estado privado.


public class Pessoa{

      private XDate nascimento;

      public void attribuiDataNascimento(XDate data){
               this.nascimento= data;
      }

      public XDate obtemDataNascimento(){
             return nascimento.
      }
}

// uso

Pessoa x = new Pessoa ();
x.attribuiDataNascimento(new XDate(1956,5,17));

O nome do método é o que vc quiser. O Java não obriga vc a usar nenhum nome especial nem nenhuma palavra reservada extra; mantendo assim a sintaxe do java exuta. Estes métodos que acessam ou alteram o estado do objeto chamam-se Acessors (Acessores) e Modifiers (Modificadores) , respectivamente.

Bom, mas pense que existem milhões de programadores java e cada um pode dar o nome que quiser… isso é bom ,mas o java oferece ferramentas de reflection que para funcionarem têm que ser baseada numa referencia que todo o mundo use. Além disso codigo padronizado é mais facil de ler e alterar. Junte a isso o openSource e verá que cada um usar o nome que quiser é ruim.
Dai a convenção de usar o nome da variável prefixado com get ou set.
Essa convensão faz parte do Design Pattern JavaBean, mas não é em si mesma um Design Pattern , é uma convensão para obdecer ao principio de encapsulamento.
Como já foi dito não é obrigatorio que existam os dois. O estado pode ser read-only (apenas leitura), write-only (apenas escrita) ou ambos.
Mas o objeto oferecer informações que não fazem parte do seu estado, como informações calculadas. Nesse caso o método não deve ser precedido de get. Exemplo

public class Pessoa{

      private XDate nascimento;

      public void attribuiDataNascimento(XDate data){
               this.nascimento= data;
      }

      public XDate obtemDataNascimento(){
             return nascimento.
      }

      public int idade(){
           return XDate.hoje().anosPassadosDesde(nascimento);
      }
}

A idade da pessoa muda conforme o tempo passa. Para a calcular eu preciso acessar o estado interno do objecto para saber quando a pessoa nasceu, eu poderia usar obtemDataNascimento() e fazer os calculos cada vez que precisasse, mas isso violaria outro principio chamado DRY (don’t repeat yourself : Não se repita). Fazendo o calculo fora do objecto eu teri a que escrever muitas vezes aquele codigo, colocando-o dentro do objecto fica muito mais simples. Mas como idade é calculada , ela não é uma propriedade do objecto Pessoa, então ela não começa com get. Começar com get significaria que getIdade() é um método de acesso, e isso não seria verdade. Exemplo : o método size() da interface Collection.
Na prática vc pode usar get tb nesses casos. É uma questão de principio e não de implementação.

Então porquê get / set

  1. para obdecer ao principio do encapsulamento do estado.
  2. os nomes são convensões popularizadas pelo design pattern JavaBean, mas eles em si mesmos não são design patterns , nem os métodos. (se a variável é boolean o getXXX é substituido por isXXX)
  3. Não é obrigatório ter o par get/set para cada propriedade. Isso depende se a propriedade é só de leitura, só de escrita, ou ambas.
  4. Resultados de cálculos ou outras operações complexas não começam com get. Exemplo : o método size() da interface Collection. Mas esta regra pode não ser usada.

a tag <jsp:getProperty > só funciona para os métosos get assim com a <jsp:setProperty > somente para os set. É um padrão de organização

na verdade estas tags funcionam com métodos de qualquer nome, des de que tu utilize a outra gambiarra padronizada, nem tão famosa quanto os gets e sets, mas que também faz parte da API de JavaBeans …
se tu criar uma classe BeanInfo pode usar qualquer nome para os metodos de leitura e escrita das tuas propriedades que as ferramentas vão se achar normalmente …
pois a classe BeanInfo vai informar para estes “consumidores” do bean, quem é o método de escrita e o metodo de leitura desta propriedade …
a unica diferença é que se tu não criar um beaninfo, o java vai criar um default que utiliza o padrão de nomenclatura get/set para as propriedades

Deu para entender bem, a resposta de todos foi muito boa, muito obrigado =)!!!
por via das dúvidas, como tbm estou aprendendo jsp e vi uma necessidade do get e set como nome “padrão” então não vou fugir a “regra” *rs!

valeu mesmo.
abraços.

5

aks amigos, de uma boa linda em OO, vai te ajudar mto no futuro

vlws e qualquer duvida soh postar ai

Saudações tiagomac,

Um comentário sobre a importância do encapsulamento:

Em Programação Orientada a Objetos, furar o encapsulamento pode ser comparado a abrir a barriga de alguém para olhar o que têm dentro ao invés de perguntar o que ele comeu no almoço.

Um dos objetivos do encapsulamento é esconder (encapsular) uma complexidade. Pois você não está interessado em saber “como” faz, mas sim o "o que "ele faz… Normalmente você não está interessado como os métodos que você implementou realizam as tarefas, mas sim quais tarefas ele realiza. Qual é a sua interfacre. O que ele recebe como parâmetro e o que ele retorna.

Outro objetivo do encapsulamento é isolar um atributo ou método. Ao invés de você utilizar o valor 1,75 (cotação do dólar) em em várias partes de seu código, você cria um getCotacaoDolar(), assim, quando a cotação mudar você não precisa varrer o código todo, o impacto será apenas em getCotacaoDolar();

eh pra manter o estado do objeto e ter facil manutencao