[Resolvido]Acessando atributos private da superclasse através da subclasse

Olá pessoal, tudo bem?

Então, eu tenho algumas dúvidas em relação à encapsulamento e herança.

public class A
{
   private int atributo;
   
   public void setAtributo (int valor)
   {
      atributo = valor;
   }
   
   public int getAtributo ()
   {
      return atributo;
   }
}

Isso seria um encapsulamento bem simples, certo?

Agora o meu problema é o seguinte:

public class B extends A
{
   public void gravar ()
   {
      int numero = 10; // um valor qualquer.
      /* Aqui está o problema, qual desses dois devem ser usados, 
      supondo que eu utilizaria o getAtributo, ou seja, precisaria resgatar 
      o valor 10 que eu atribui à variavel numero.*/
      super.setAtributo (numero); //este?
      this.setAtributo (numero); // ou este?
   }
}

Muito obrigado!

A segunda opção. ou simplesmente:

public class B extends A { public void gravar () { int numero = 10; // um valor qualquer. setAtributo (numero); // ou este? } }

A primeira você só usa se tiver um comportamento sobrescrito em B, e quiser usar o comportamento de A.

Exemplo:

public class B extends A { public void setAtributo(int valor) { if (valor < 10) throw new ArgumentException("O valor em B não pode ser menor que 10!"); super.setAtributo(valor); //Agora chama o setAtributo de A, que não faz validação e atribui. } ... }

Entendi, mas isso funciona mesmo se o atributo da classe A for private?
Quando ele é private, ele é ou não herdado?

E o valor que foi gravado nessa variável vai ficar “ativo” até o final da minha classe B?

Só se for protected, default (e estiver no mesmo pacote) ou public.

Com private não funciona, para a classe debaixo é como se o método não existisse.

[quote=ViniGodoy]Só se for protected, default (e estiver no mesmo pacote) ou public.

Com private não funciona, para a classe debaixo é como se o método não existisse.[/quote]

Duas dúvidas:
1 - Tanto para método quanto para atributo, o que for private não é herdado, certo?

2 - Então para criar este encapsulamento eu poderia colocá-la como public, mas na hora de alterar a variável da superclasse eu colocaria

super.atributo = valor;

e para alterar a da subclasse eu colocaria

this.atributo = valor;

Correto? Só que isso não tornaria o meu encapsulamento desnecessário?

Calma… se deixares public, não há encapsulamento… Deves proteger teu atributo, deixar ele acessível somente pelo pai e pelo filho… Aí sim podes encapsular e nem precisa chamar super ou this…

Abs []

[quote=adriano_si]Calma… se deixares public, não há encapsulamento… Deves proteger teu atributo, deixar ele acessível somente pelo pai e pelo filho… Aí sim podes encapsular e nem precisa chamar super ou this…

Abs [][/quote]

OK, mas como eu o protejo sem que ele seja private? Já que private não é herdado…

O private é herdado, mas não é acessível. Se você acessar um atributo private através de um get ou set que não seja private, vai funcionar normalmente.

O que você tem que se perguntar é se você quer mesmo que outras classes tenham ou não acesso direto a esse atributo:

  1. Se você quiser que só sua classe tenha acesso direto, mas as demais só possam fazer através de métodos get e set, use o private;
  2. Se você quiser que sua classe e as do mesmo pacote tenham acesso direto, mas as demais só com get e set, use o default (não escreva nada);
  3. Se você quiser que sua classe, as do mesmo pacote, e as filhas (onde quer que estejam) tenham acesso direto, e o resto só por get e set, use protected;
  4. Se você quiser que todos tenham acesso direto (péssima idéia) use public.

Note que classes filhas tem um nível de acesso especial na maioria das linguagem, pois elas representam a relação é um. Mas é uma discussão sem fim se elas devem ou não ter acesso direto, ou protected. Eu dificilmente uso protected em atributos, geralmente eu reservo para métodos mesmo.

Um exemplo de atributo encapsulado:

[code]public class Exemplo {
private int x; //Somente exemplo altera x diretamente

//Permite que classes do mesmo pacote e filhas troquem o valor
protected void setX(int valor) {
if (valor < 0)
throw new IllegalArgumentException(“O valor tem que ser maior que 0!”);
this.valor = valor;
}

//Permite que qualquer um leia o valor
public int getValor() {
return valor;
}
}[/code]

Note que uma classe filhas e do mesmo pacote podem mexer no valor, desde que use um valor >= 0. Classes de outros pacotes e que não sejam filhas, só podem ler o valor. O atributo portanto está encapsulado.

Não é necessário usar super. sempre. Só se houver ambiguidade. Por exemplo:

public class ExemploFilho extends Exemplo { //Permite que qualquer um troque o X para 50 public void trocarX() { setX(50); //Essa classe não define setX. Então isso equivale à super.setX(), já que o método é herdado. } }

Você só precisa explicitar o super, se você tivesse sobrescrito o setX e seu interesse não fosse chamar seu próprio setX, mas o do pai.

Um atributo protected seria visível na subclasse. Ou seja, você estaria confiando à subclasse a capacidade total e irrestrita de alterar aquele atributo. Não há proteção, mas como a subclasse é um tipo especializado da super (relação é um), você assume que os programadores que estiverem fazendo a herança sabem o que estão fazendo. Entretanto, o atributo fica com acesso protegido a outras classes do sistema, de outros pacotes.

1 curtida

O private é herdado, mas não é acessível. Se você acessar um atributo private através de um get ou set que não seja private, vai funcionar normalmente.

O que você tem que se perguntar é se você quer mesmo que outras classes tenham ou não acesso direto a esse atributo:

  1. Se você quiser que só sua classe tenha acesso direto, mas as demais só possam fazer através de métodos get e set, use o private;
  2. Se você quiser que sua classe e as do mesmo pacote tenham acesso direto, mas as demais só com get e set, use o default (não escreva nada);
  3. Se você quiser que sua classe, as do mesmo pacote, e as filhas (onde quer que estejam) tenham acesso direto, e o resto só por get e set, use protected;
  4. Se você quiser que todos tenham acesso direto (péssima idéia) use public.

Note que classes filhas tem um nível de acesso especial na maioria das linguagem, pois elas representam a relação é um. Mas é uma discussão sem fim se elas devem ou não ter acesso direto, ou protected. Eu dificilmente uso protected em atributos, geralmente eu reservo para métodos mesmo.

Um exemplo de atributo encapsulado:

[code]public class Exemplo {
private int x; //Somente exemplo altera x diretamente

//Permite que classes do mesmo pacote e filhas troquem o valor
protected void setX(int valor) {
if (valor < 0)
throw new IllegalArgumentException(“O valor tem que ser maior que 0!”);
this.valor = valor;
}

//Permite que qualquer um leia o valor
public int getValor() {
return valor;
}
}[/code]

Note que uma classe filhas e do mesmo pacote podem mexer no valor, desde que use um valor >= 0. Classes de outros pacotes e que não sejam filhas, só podem ler o valor. O atributo portanto está encapsulado.

Não é necessário usar super. sempre. Só se houver ambiguidade. Por exemplo:

public class ExemploFilho extends Exemplo { //Permite que qualquer um troque o X para 50 public void trocarX() { setX(50); //Essa classe não define setX. Então isso equivale à super.setX(), já que o método é herdado. } }

Você só precisa explicitar o super, se você tivesse sobrescrito o setX e seu interesse não fosse chamar seu próprio setX, mas o do pai.

Um atributo protected seria visível na subclasse. Ou seja, você estaria confiando à subclasse a capacidade total e irrestrita de alterar aquele atributo. Não há proteção, mas como a subclasse é um tipo especializado da super (relação é um), você assume que os programadores que estiverem fazendo a herança sabem o que estão fazendo. Entretanto, o atributo fica com acesso protegido a outras classes do sistema, de outros pacotes.[/quote]

:smiley: Agora entendi perfeitamente bem! Então vou continuar com meus atributos privados e meus métodos públicos (que é o que estou precisando no momento).

Muitíssimo obrigado, eu aprendo muito aqui no GUJ.

PS: depois que eu conseguir resolver este meu programa (segredo por enquanto) eu disponibilizo um desafio la no tópico criado para isso e depois eu posto o meu programa (se der tudo certo!)…

Agora, só atributos privados e gets e sets não garantem um bom encapsulamento. Se quiser se aprofundar um pouco mais sobre o assunto, leia:
http://www.guj.com.br/posts/list/104592.java#564414

1 curtida