Getter de um objeto -> ferindo o princípio de encapsulam

7 respostas
M

vejam o exemplo:
public class MinhaClasse {
public int idade;
}

qq um poderia fazer: (new MinhaClasse()).idade = xxxxxxxxx; isso fere o encapsulamento, visto que qq um poderia alterar livremente o valor do campo nome, mesmo que a alteração fosse para um nome invalido. entao eu faria:
public class MinhaClasse {
   private int idade;

   public void setIdade(int novaIdade) {
      // faço as validações necessarias e altero o campo nome se quiser..
   }

   public int getIdade() {
      return idade;
   }
}
ae, fica beleza, nao é? assim eu tenho a possibilidade de garantir a consistencia do campo nome...

mas se fosse com um objeto:
public class MinhaClasse {
   private MinhaClasse2 outraClasse;

   public MinhaClasse2 getOutraClasse() {
      return outraClasse;
   }
}

eu nao posso acessar diretamente outraClasse, mas posso acessa-la através do seu getter, e alterar seu valor livremente, produzindo possiveis valores inconsistentes para esse atributo...

que sugestão vcs me dão para contornar esse problema? se nao me engano(avisem se eu estiver falando merda..), parece q há classes que permitem que se crie um clone dela..... o objeto clonado terá os mesmos valores que o objeto original, mas será localizado em outra posição da memoria, podendo então o clone ser alterado sem que o objeto original sofra qualquer alteração... mas é toda classe que possui tal funcionalidade?

[color="red"]Colocado BBCode code ! Por favor tome cuidado com isso![/color]

7 Respostas

F

vc pode contornar isso deixando todas as variaveis de instancia da classe MinhaClasse2 como private, e pondo metodos set/get nela q verifiquem os dados…

M
mas nada impede o cliente da minha classe de fazer algo tipo:

(instancia de MinhaClasse).getOutraClasse() = new MinhaClasse2();

ou (instancia de MinhaClasse).getOutraClasse() = null;

ou nao?

C

Olá mmpaulo vc está correto nas suas observações. Amelhor solução é vc implementar a interface Cloneable para obter um clone do objeto. Desta forma o objeto original não tem seu estado alterado, e o clone sim, desta forma vc pode usar dois objetos com estados iniciais identicos (sendo eles os mesmos objetos) só que um será alterado e o outro não.
Eis um exemplo de código baseado na sua exposição:

public class MinhaClasse {

private MinhaClasse2 outraClasse;

    public MinhaClasse2 getOutraClasse(){
        return (MinhaClasse2)this.outraClasse.clone();
    }
}

class MinhaClasse2 implements Cloneable{

public Object clone() {
    Cloneable clone = new MinhaClasse2();
        return clone;
}

}

Abraço
Carlos

M

nao, vc esta errado. hehehehe :)

qnd se retorna o objeto no método getter, esta se retornando uma cópia da referencia a esse objeto, e não a referencia em si, pq essa referencia é da classe q contém o objeto... então qnd vc atribuir null a essa referencia, nao esta atribuindo null ao objeto encapsulado.. pq é uma copia da referencia.. e nao a referencia... olha ai o exemplo...

public class Teste { 

	private A a;
	
   public static void main(String args[])
   { 
   	Teste h = new Teste();
   	
   	h.setA( new A() );
   	
   	A s1 = h.getA();
   	
   	s1 = null;
   	
   	System.out.println( h.getA() );
   }
   
   A getA() { return a; }
   void setA( A x ) { a = x; }
}

class A { }
H

Matheus está correto. Métodos get te retornam valores, neste caso uma referência ao objeto MinhaClasse2 armazenado na instância MinhaClasse. Para alterar o valor interno, você precisaria de um método set. Portanto, a notação

(instancia de MinhaClasse).getOutraClasse() = null;

não é válida.

É verdade que eu poderia pegar a referência pelo get e alterar o objeto MinhaClasse2. Mas essa alteração seria feita pelos métodos get e set de MinhaClasse2, que não deveriam permitir alterações que provocassem um estado inconsistente. Mas se você quiser mesmo impedir que uma classe externa tenha acesso ao mesmo objeto armazenado internamente, faça o get de MinhaClasse retornar um clone. Para tal, você precisa que MinhaClasse2 implemente a interface java.lang.Cloneable e sobrescreva o método protected Object clone() da classe Object. Dê uma olhada na documentação a respeito [size=“12”]aqui[/size].

Até mais,

M

nããã. é claro q tu pode da um get num atributo de uma classe q retorne um objeto e alterar os atributos desse objeto q vai alterar o objeto da classe tb, mas tu nao pode mudar pra onde a referencia realmente aponta, ou seja, mudar o objeto q referencia aponta na memoria…

R

saudades dos pointers… :lol:

Criado 30 de setembro de 2004
Ultima resposta 17 de out. de 2004
Respostas 7
Participantes 6