Primeira vez aqui? Seja bem vindo e cheque o FAQ!
x

Como o python trata encapsulamento em Programação Orientada a Objeto?

0 votos
2,206 visitas
perguntada Abr 2, 2016 em Programação Computacional por danielcajueiro (5,786 pontos)  
Compartilhe

1 Resposta

+1 voto
respondida Abr 2, 2016 por danielcajueiro (5,786 pontos)  

O python usa _ (underscore) para explicitar se um atributo (método) é publico, protegido ou privado:

name - public: pode ser acessada de qualquer lugar

_name - protected: Como um membro publico, mas não deve ser acessada

__name - private: Não pode ser acessada de fora da classe

Exemplo:

class Encapsulation(object):
    def __init__(self, a, b, c):
        self.myPublic = a
        self._myProtected = b
        self.__myPrivate = c

if __name__ == '__main__':

    myEncapsulation=Encapsulation(1,2,3)

    print(myEncapsulation.myPublic)
    print(myEncapsulation._myProtected)
    print(myEncapsulation.__myPrivate)    

O terceiro print retorna um erro:

AttributeError: 'Encapsulation' object has no attribute '__myPrivate'
comentou Abr 2, 2016 por Caue (231 pontos)  
O atributo privado pode ser acessado da seguinte forma:

class Encapsulation(object):
    def __init__(self, a, b, c):
        self.myPublic = a
        self._myProtected = b
        self.__myPrivate = c

if __name__ == '__main__':

    myEncapsulation=Encapsulation(1,2,3)

    print myEncapsulation.myPublic
    print myEncapsulation._myProtected
    print myEncapsulation._Encapsulation__myPrivate
comentou Abr 2, 2016 por danielcajueiro (5,786 pontos)  
Sim, fantástico! Obrigado pelo complemento! Não sei se você usa o Spyder também, mas esse dado aparece quando começamos a digitar "myEncapsulation" e inclui o "." (ponto). Então dá pra descobrir como acessar essa variável!
comentou Abr 7, 2016 por Saulo (456 pontos)  
Sobre este assunto, descobri uma pequena diferença entre Python e C++. Aparentemente, métodos virtuais privados são tratados de forma diferente nas duas linguagens. Segue um exemplo.

As chamadas neste exemplo são feitas todas por métodos da classe base, func e func2. func chama um método (virtual) público, enquanto func2 chama um método (virtual) privado.

Considere o seguinte código em Python:

class Base():
    def virt(self):
        print "Base::virt()"

    def __virt2(self):
        print "Base::__virt2()"

    def func(self):
        print "Base::func()"
        self.virt()

    def func2(self):
        print "Base::func2()"
        self.__virt2()

class Derived(Base):

    def __init__(self):
  # only way I've found so far is to edit the dict like this
        #Base.__dict__['_Base_virtual'] = self.virtual
        return

    def virt(self):
        print "Derived::virt()"
        
    def __virt2(self):
        print "Derived::__virt2()"

if __name__ == '__main__':
    d = Derived()
    d.func()
    d.func2()

A execução deste código gera a seguinte saída:
Base::func()
Derived::virt()
Base::func2()
Base::__virt2()

A saída sugere que somente o método público é chamado da classe derivada, enquanto todos os outros são da classe base.

Agora considere o seguinte código em C++:

#include <iostream>

using namespace std;

class Base {
    private:
        virtual void virt2() { cout << "Base::virt2()" << endl; };

    public:
        virtual ~Base() {}
        virtual void virt() { cout << "Base::virt()" << endl; };
        void func() { cout << "Base::func()" << endl; virt(); };
        void func2() { cout << "Base::func2()" << endl; virt2(); };
};

class Derived : public Base {
    private:
        virtual void virt2() { cout << "Derived::virt2()" << endl; };

    public:
        virtual ~Derived() {}
        virtual void virt() { cout << "Derived::virt()" << endl; };
};

int main(int argc, char* argv[])
{
    Derived d;
    d.func();
    d.func2();

    return 0;
}

A execução deste código gera a seguinte saída:
Base::func()
Derived::virt()
Base::func2()
Derived::virt2()

A saída sugere que ambos os métodos virtuais (público ou privado) são chamados da classe derivada.

Caso eu não tenha cometido nenhum equívoco, esta é uma diferença sutil que pode fazer você perder muitas horas debugando o seu código!
...