Encapsulamento de dados é um recurso presente em linguagens que seguem o paradigma orientado a objetos. Esse recurso tem como objetivo restrigir o acesso direto a informação, ou seja, ele protege informações que não devem ser alteradas em qualquer parte do programa. Com isso podemos entender que quem está de fora apenas sabe que o serviço é realizado mas não sabe como o serviço é implementado.
Certamente quando começamos a programar orientado a objetos não vemos os benefícios que o encapsulamento de dados nos proporciona, pois, a primeira vista ele só serve para gerar mais linhas de código.
Hoje vou falar como encapsular dados na linguagem de programação Python versão 3.x. Se você já programou em alguma linguagem .Net (Visual Basic, C#) não sentirá grandes mudanças, porém, se você é um programador Java sentirá uma certa estranheza quando ler o código.
Bom sem mais demora vamos conhecer mais um pouquinho da linguagem Python e sua implementação diferente em POO.
Protegendo minhas variáveis dos Noobs
Na minha opinião o encapsulamento de dados existe, porém, não garante a total segurança do seu código. Antes de você me chamar de louco vou explicar, se você é um programador Java e ficou muito ofendido com o que eu disse ... me desculpe essa não foi a intenssão! Mas Sr.Programador Java, seu código não está seguro só porque o Sr. usa o modificador de acesso private em suas variáveis de instância, se alguém quiser saber quais são as variáveis presentes em determinadas classes de seu sistema ele pode fazer isso utilizando a própria API do Java a nossa querida Reflection. Logicamente que trabalhar com essa API não é algo trivial, porém, pense duas vezes antes de desafiar um nerd dizendo que seu código está 100% seguro.
Em Python a história também não é diferente, se alguém quiser saber quais variáveis sua classe tem essa pessoa vai acabar descobrindo de um jeito ou de outro. Por isso que a ideia principal de Python é que tudo seja public e somente o necessário, seja private. Muitas vezes quando estamos aprendendo POO o pessoal costuma dizer: "Grande parte das vezes sua classe terá atributos de instância privado e métodos públicos". Mais nem sempre é assim, podemos realmente ter variáveis em nossas classes que não precisam serem private.
Bom, se você está certo que precisa ter variáveis private em sua classe e não quer que ela seja acessível fora da classe onde ela foi especificada, então você terá que informar primeiramente que ela será private, para que o interpretador Python saiba disso. Para dizer que um atributo de instância é private em python utilizamos dois underline antes do nome da variável. Exemplo:
class Gato:
__raca = None
...
Com isso dizemos ao interpretador que o atributo raça é privado. Agora temos que construir dois métodos, um para setar (setter) e outro para recuperar (getter) o valor do atributo. No python 3.x foi introduzida uma sintaxe muito elegante para realizar esse serviço. Veja:
class Gato:
def __init__(self):
__raca = None
@property
def raca(self):
return __raca
@raca.setter
def raca(self, value):
self.__raca = value
Viu como é simples? Bom o que fizemos foi definir dois métodos (em python pode-se falar função da classe), onde no primeiro definimos o getter e o segundo o definimos o setter. Observe que os dois métodos tem o mesmo nome, mas possuem anotações diferentes. A primeira anotação @property indica o método é um getter e a segunda anotação @raca.setter indica que o método é um setter , perceba que a segunda anotação é bem diferente da primeira, nela devemos informar o nome do atributo seguido de ponto e a palavra setter.
Podemos definir que um atributo seja apenas read-only. Para fazer isso basta excluir o método setter. Veja:
class Gato:
def __init__(self):
__raca = None
@property
def raca(self):
return __raca
Agora observe como fica natural o acesso aos atributos:
if __name__ == '__main__':
mimo = Gato()
megui = Gato()
mimo.raca = 'angorá turco'
mimo.idade = 2
megui.raca = 'siames'
megui.idade = 1
print('Megui é da raça {}, e tem {} ano(s) de idade.'.format(megui.raca, megui.idade))
print('Mimo é da raça {}, e tem {} ano(s) de idade.'.format(mimo.raca, mimo.idade))
Pessoal o post se encerra por aqui! Espero que tenham gostado de aprender um pouco mais sobre Python e veja vocês em um próximo post, até lá e BONS ESTUDOS!