Encapsulamento

Encapsulamento

por Bruno Sesso -
Número de respostas: 5

Surigiram algumas dúvidas a respeito de encapsulamento.  Pelo que eu entendi, devemos usar métodos para acessar os atributos de uma classe, assim não os acessamos diretamente.


Não entendi direito se o problema é acessar os atributos diretamente, ou se é o fato de termos de acessa-los, ou ambos!
Ou seja, se eu tenho uma classe com 5 atributos, seria ruim eu ter getters and setters para todos eles? isso quebraria o encapsulamento?

Em resposta à Bruno Sesso

Re: Encapsulamento

por Rafael Reggiani Manzo -

Olá Bruno,

Encapsulamento consiste de um mecanismo para esconder informação sobre a sua classe e permitir o acesso parcial a ela, conforme a necessidade de outras classes que dependam dela. Isso é uma das medidas, e a mais importante, que aplicamos durante o desenvolvimento para evitar alto acoplamento entre classes.

Respondendo a sua pergunta, permitir o acesso direto aos atributos diretamente é ruim.

Imagine que você tenha a classe Pessoal com atributos públicos cpf e nome. Digamos que exista uma segunda classe Compra que utilize Pessoa e precise modificar o atributo cpf de acordo com novos dados que ela receba. Como cpf é público, Compra acessa cpf diretamente e o modifica como o esperado. Mas gostaríamos de começar a validar o cpf para evitar fraudes. Como, Compra acessa diretamente esse atributo, ela passa a ter a responsabilidade de também validá-lo e saber como deve ser feita tal validação. Agora imagine que existam mais duas classes acessando diretamente esse atributo. Elas também precisam conhecer toda essa lógica e se uma delas não validar corretamente todas as demais quebram sem você nem saber a fonte do problema.

Deu para ver que nesse exemplo tivemos tanto um problema de acoplamento quanto de coesão que seria evitado pelo simples encapsulamento.

Respondendo a parte final da sua pergunta, ter getters e setters para todos os atributos não é uma quebra clara de encapsulamento, mas é um forte indício. Pense sempre em encapsulamento, como esconder informações que não importam às demais classes. Talvez a sua classe de fato precise de getters e setters em todos os atributos, como é o caso do padrão de DAO (Data Access Object), mas tenha sempre o cuidado de avaliar a real necessidade de dar acesso às informações.

Respondi tudo?

Em resposta à Rafael Reggiani Manzo

Re: Encapsulamento

por Eric Lee -

Rafael, 

pelo que eu li de python quanto temos:

class Exemplo:

    def __init__(self)

         self.atributo = 2

a = Exemplo()

 

eu posso acessar o atributo e modificar o valor com 'a.atributo = 2' por exemplo,

um jeito de evitar isso seria fazer o atributo ser privado com o '_' mas os artigos em python dizem nao ser uma boa prática.

 

A minha questão é se vale a pena fazer os getters? sendo que os atributos são tao acessiveis assim.

Em resposta à Eric Lee

Re: Encapsulamento

por André Meneghelli -

Olá Eric, quando seguimos a idéia de "somos todos grandinhos" pensamos que um atributo não será acessado diretamente por um usuário de uma de nossas classes.

Mas como este usuário vai trabalhar com nossa classe sem saber o que esperamos?

Os setters e os getters são uma maneira de deixar claro como esperamos que nossa classe seja usada.

Em resposta à Eric Lee

Re: Encapsulamento

por Eric Kenji Yoshikawa -

Existe um jeito de fazer com que não seja acessado diretamente.

Basicamente:

class Pokemon():

        @property
        def nome(self) :  return self.__nome

        @nome.setter
        def nome(self, nome) :  self.__nome = nome

        def __init__(self, nome):
                self.__nome = nome

 

Se você tentar:

x = Pokemon("Pikachu")

x.__nome   --> não é acessivel

x.nome --> Pikachu

 

Se você retirar o @nome.setter(...), o atributo só pode ser "setado" dentro da classe, o que às vezes é interessante.

Se você retirar o @property(...), o atributo vira "private" e não pode ser acessado externamente (na verdade tem como, mas não é "simples")

Na verdade o "duplo underline __ " é substituido pelo nome da classe pelo Python, por isso x.__nome não existe.