Monday, December 22, 2008

Python - hermetyzacja, enkapsulacja z punktu widzenia programisty C++

W C++ kiedy chcieliśmy ukrywać informacje w klasach pisaliśmy po prostu metody (settery i gettery), które ustawiały lub pobierały wartości konkretnych parametrów. Właściwie - tworząc prywatny atrybut klasy (zaczynający się od dwóch podkreśleń) i pisząc do niego gettery i settery możemy dosłownie przekopiować rozwiązanie znane nam z C++. Możesz nadal pisać
obiekt.setX(10)
obiekt.getX()

Jednak :) Python umożliwia Ci używanie obiektu tak jakby był publiczny:
obiekt.x = 10
obiekt.x

dopisując do nich funkcje, wywoływane w trakcie przypisywania wartości lub odwoływania się do niej. Wszystko dzięki strukturze property.
Stwórzmy więc naszą klasę :) chowając w niej prawdziwe zmienne.
class Klasa(object):
    def __init__(self):
        self.__x = None

    def getx(self):
        return self.__x

    def setx(self, value):
        self.__x = value

    def delx(self):
        del self.__x

    x = property(getx, setx, delx, "I'm the 'x' property.")
Podczas tworzenia obiektu zostanie powołany do życia prywatny atrybut __x. Nie ma do niego dostępu z zewnątrz. Teraz - piszemy normalne metody takie jak w C++ :) getx, która zwróci jego wartość, setx, która ustawi jego wartość oraz dodatkowo delx, która skasuje atrybut :]
Cała "sztuczka" opiera się na końcowym stworzeniu atrybutu klasy "x" i przypisania do niego stworzonego gettera, settera, "delletera" oraz docstringa - opisu zmiennej. Od teraz możemy korzystać z "x" tak jakby był to atrybut klasy faktycznie jednak wywoływały się będą stworzone przez nas funkcje :)
obiekt = Klasa()
obiekt.x = 10 # Wywoła się tak naprawdę setx(10) self.__x = 10
print obiekt.x # Wywoła się tak naprawdę getx() return self.__x
del obiekt.x # Wywoła się tak naprawdę delx() del self.__x
Bardzo przyjemna i użyteczna metoda :] kontrolowania dostępu do atrybutów z zewnątrz przy niekomplikowaniu elegancji oraz prostoty składni :)

1 comment:

Log_1 said...

"Podczas tworzenia obiektu zostanie powołany do życia prywatny atrybut __x. Nie ma do niego dostępu z zewnątrz"

Python pełny jest niespodzianek, jednak można się do niego dogrzebać bez użycia property:)

przykład:

class myClass:
~~def __init__(self):
~~~~self.__x = 6

~~def getX(self):
~~~~return self.__x

m = myClass()
print m._myClass__x
m._myClass__x = 7
print m.getX()

ogólnie ciekawy post, pozdrawiam.