Sabemos que membros private não podem ser acessados fora da classe em que foram declarados.
Mas em relação as suas subclasses?
E se eu quiser esconder algum dado das subclasses?
Veremos nesse artigo, de nosso curso online de Java, como proteger membros de uma classe, limitar e controlar o acesso aos dados importantes.
Herança de atributos public
Na prática, elementos public são utilizados em variáveis e métodos universais, onde não há problema nem necessidade de segurança daquele dado. Exemplo: horas, constantes, variáveis globais, nome do programa ou da empresa etc.
O nome já fala tudo por si só, é público.
Herança de atributos private
Diferente dos elementos public, os private são informações 'escondidas', ou no mínimo controladas.Por exemplo, é bem comum ver todas as variáveis de uma classe definidas como priva, e usar métodos public do tipo set, para dar um valor a esta variável.
Ora, se o set() for só para definir o valor da variável, essa atitude é totalmente inútil.
Só devemos usar o set() para manipular variáveis private quando fizemos algo a mais, como checar se o valor recebido é positivo, se está dentro do intervalo que esperamos ou mesmo para contar quantas vezes aquela variável foi acessada.
Isso tudo tem um motivo: variáveis private não podem ser acessadas nem por suas subclasses.
Tenha isso em mente: priva é sinônimo de segurança.
O seguinte exemplo, dando continuidade aos exemplos de Herança de nossa tutorial de Java passado, vamos mostrar que é impossível acessar diretamente a variável 'senhaPai' a partir da subclasse "Filha":
-->Heranca.java
public class Heranca { public static void main(String[] args) { Filha filha = new Filha(); } }
-->Pai.java
public class Pai { private String senhaPai; public Pai(){ this.senhaPai = "papaidanadao"; } }
-->Filha.java
public class Filha extends Pai { public Filha(){ System.out.println(senhaPai); } }
Obteremos o seguinte erro:
"The field Pai.senhaPai is not visible"
Literalmente: o campo Pai.senhaPai não é visível. Nem pra classe filha a senha da classe pai é vista.
Isso que é segurança, hein?
Pense bem se seus atributos devem ser private ou não. Lembre-se que se não forem, outras pessoas - hackers - podem usar isso para obter informações de sua aplicação.
Herança de atributos protected
Vamos agora introduzir outro modo de declarar seus atributos, o modificador de acesso protected.O protected é pra quando você não quer deixar um atributo public, livre para todos.
Porém, você quer compartilhar ele com as subclasses. O protected é um intermediário entre public e private.
É um segredo de família.
Por família entende: a superclasse, as subclasses e classes do mesmo package.
Para todos as outras classes, atributos protected são invisíveis. Ou seja, estamos protegendo do acesso externo.
Outro detalhe importante: quando atributos são declarados como public ou protected, eles continuarão como public ou protected.
Lembra que dissemos que subclasses podem ser superclasse também? Ora, basta declarar outra classe que extends a classe Filha, e teremos uma subclasse da subclasse Filha.
Então, vamos chamar essa classe de Neta.
Se declararmos uma variável como protected na classe Pai, ela será protected na classe Filha, e será vista como protected na classe Neta. O mesmo para public.
Vamos criar dois pacotes: o package "Familia", que irá conter as classes "Heranca", "Pai", "Filha" e "Neta ; e o pacote "Vizinho", que contém a classe "Vizinho".
Para fazer isso basta escrever no início: package Familia ou package Vizinho
A senha do pai poderá ser vista por qualquer um do pacote "Familia", mas obteremos um erro quando tentarmos ver essa senha através da classe "Vizinho", pois o vizinho não faz parte do pacote "Familia".
Nosso exemplo ficará assim:
-->Heranca.java
package familia; import Vizinho.Vizinho; public class Heranca { public static void main(String[] args) { Neta neta = new Neta(); System.out.println("Senha vista da classe Herança: "+neta.senhaPai); Vizinho vizinho = new Vizinho(neta); } }
-->Pai.java
package familia; public class Pai { protected String senhaPai; public Pai(){ this.senhaPai = "papaidanadao"; } }
-->Filha.java
package familia; public class Filha extends Pai { public Filha(){ System.out.println("Senha vista pela filha: "+senhaPai); } }
-->Neta.java
package familia; public class Neta extends Filha{ public Neta(){ System.out.println("Senha vista pela Neta: " + senhaPai); } }
-->Vizinho.java
package Vizinho; import familia.Neta; public class Vizinho { public Vizinho(Neta neta){ System.out.println("Senha vista pelo vizinho: "+neta.senhaPai); } }
Obtemos o resultado:
Senha vista pela filha: papaidanadao
Senha vista pela Neta: papaidanadao
Senha vista da classe Herança: papaidanadao
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
The field Pai.senhaPai is not visible
Ou seja, podemos ver a senha do Pai por qualquer uma das subclasses e classes do pacote "Familia".
Porém, ao tentarmos ver por uma classe que não faz parte nem do pacote "familia" nem é subclasse de "Pai", "Filha" ou "Neta" obtemos um erro, pois a senha do pai não será visível para o vizinho.
Seguro esse Java, não?
Não é à toa que ele é bastante usado por empresas, como seu bank online. Pode confiar no Java!
9 comentários:
Copiei os códigos acima e tentei executalos, da erro de compilacao 5 erros, poderiam me ajudar com isto!?
Claro, copie e cole os erros que apareceram.
Primeiramente queria dizer que na minha opinião este é um dos melhores sites de aprendizagem, gosto bastante de sua metodologia e dicas. Parabéns!
Gostaria de saber o seguinte, se uma variável de instância do tipo private 'melhora' na questão da segurança, uma invasão de um hackers por exemplo, como estes não conseguem visualizar a informação da variável se ele pode utilizar os métodos setts e getts para atribuir e retornar o valor dela?
Já tinha bastante experiência de programação em outras linguagens mas torcia o nariz para Java diante do que já havia visto.
O seu curso, muito bem estruturado, acabou com todos os meus preconceitos. :)
Parabéns!
Kleber JS,
Os métodos Getters e Setters, de fato, permitiriam acesso não autorizado se forem utilizados sem prescrição alguma. Isso depende do programador, e como uma boa prática de programação você deve utilizar tais métodos se forem realmente necessários, ou seja, quando você realmente querer que uma outra classe veja e/ou altera os dados em uma variável. O que quero dizer é que você deve ter em mente o acesso que você quer permitir a outras classes, pois, talvez, algo pode não sair bem como pensou.
Muito bom! Fantásticas suas explicações neste site! É minha referência agora!!!
abraços!!!
Ótimo exemplo. Mas o que acha de colocar uma outra situação na qual o vizinho herda de Neta (um familiar que é vizinho). Neste caso, ficaria mais fácil de diferenciar da visibilidade default.
MODIDIFICADOR | Clase | Mesmo pacote | Pacote diferente (subclasse) | Pacote diferente (global)
public x x x x
protected x x x
default x x
private x
package vizinho;
import familia.Neta;
public class Vizinho extends Neta{
public Vizinho(){
System.out.println("Senha vista pelo vizinho: "+senhaPai);
}
}
Para funcionar tive que mudar no inicio a opção Criar Classe Principal de
heranca.Heranca para familia.Familia, de modo que criou Familia.Java e não Heranca.Java.
Também tive que mudar no programa principal, onde tem o main...
de public class Heranca {
para public class Familia {
Muito bem explicado, parabéns !!
Postar um comentário