W poprzednich częściach lekcji na temat programowania obiektowego w Python, nauczyliśmy się co to jest klasa, obiekt, dziedziczenie, a nawet czym są, i jak wykorzystywać metody abstrakcyjne. Zanim przejdziemy do wykonania naszego mini projektu, został nam jeszcze temat hermetyzacji, zwanej również enkapsulacją. Zaczynajmy!

O ile pojęcia te brzmią groźnie, są o wiele łatwiejszym tematem niż dziedziczenie.

Cała idea polega na ukrywaniu wybranych parametrów oraz metod klasy, tak aby nie były dostępne z zewnątrz. A jedynie na użytek wewnętrzny klasy.

Dlaczego mieli byśmy chcieć to robić? Odpowiedź jest prosta.

  • Aby udostępniać na zewnątrz klasy, tylko to, co jest niezbędne.
  • Aby nie dać opcji ‚zepsucia’ naszej klasy,
  • oraz, aby korzystanie z niej było prostsze i bardziej intuicyjne

Spójrzmy na poniższą klasę:

class samochód:
    
    def __init__(self):
        
        self.silnik = False
        self.bieg = 0
        self.prędkość= 0
        
    def uruchom(self):
        self.silnik = True
    
    def wyłącz(self):
        self.silnik = False
    
    def biegNastępny(self):
        if self.bieg <= 6: self.bieg += 1; print(self.bieg)
            
    def biegPoprzedni(self):
        if self.bieg >= 0: self.bieg -= 1; print(self.bieg)
            
    def przyspiesz(self):
        if self.silnik == True and self.bieg > 0 : self.prędkość += 10; print(self.prędkość)
        
    def hamuj(self):
        if self.prędkość >= 10: self.prędkość -= 10
        else: self.prędkość = 0
        print(self.prędkość)
    
car = samochód()
car.biegNastępny()
car.uruchom()
car.przyspiesz()
car.hamuj()

Ta mała, niewinna klasa, odpowiada za działanie samochodu. Zwróćmy uwagę na jej metody. Przykładowo metoda przyśpiesz, zadziała tylko jeżeli ‚silnik==True’ i ‚bieg>0’, co jest absolutnie logicznie. Z kolei metoda ‚biegNastępny()’, zmieni bieg, tylko jeżeli już nie jedziemy na najwyższym, 6-tym biegu. Metody tej klasy, zawierają w sobie podstawową logikę działania samochodu, której nie pozwalają zepsuć.

Niestety, biorąc pod uwagę, że kluczowe zmienne, takie jak silnik, bieg, prędkość, są dostępne z po za klasy, bardzo łatwo zakłócić jej działanie, przypisując im różne wartości, jak ‚car.bieg = -1’, albo ‚car.bieg = 7’.

Rozwiązaniem jest hermetyzacja. Alternatywnie nazywana, enkapsulacją. Czyl ukrycie tych zmiennych, aby pozostały widoczne, tylko wewnątrz tej klasy.

A robi się to poprzez zmianę nazw zmiennych, czy też metod które chcemy utrzymać, jako metody wewnętrzne, dodając przedrostek ‚__’. I tym samym nasz kod, mógłby wyglądać następująco:

class samochód:
    
    def __init__(self):
        
        self.__silnik = False
        self.__bieg = 0
        self.__prędkość= 0
        
    def uruchom(self):
        self.__silnik = True
    
    def wyłącz(self):
        self.__silnik = False
    
    def biegNastępny(self):
        if self.__bieg <= 6: self.__bieg += 1; print(self.__bieg)
            
    def biegPoprzedni(self):
        if self.__bieg >= 0: self.__bieg -= 1; print(self.__bieg)
            
    def przyspiesz(self):
        if self.__silnik == True and self.__bieg > 0 : self.__prędkość += 10; print(self.__prędkość)
        
    def hamuj(self):
        if self.__prędkość >= 10: self.__prędkość -= 10
        else: self.__prędkość = 0
        print(self.__prędkość)
    
car = samochód()
car.uruchom()
car.biegNastępny()
car.przyspiesz()
car.hamuj()
car.wyłącz()

Natomiast próba odwołania się do zmiennej, po za klasy, skończyła by się następująco:

Podsumowując. Hermetyzacja jest niezwykle użytecznym mechanizmem, pozwalającym nam ukryć szczegóły implementacji naszej klasy. Jest to również, przez wielu programistów, uznawane jako dobra praktyka. Wszystkie zmienne jakie ma dana klasa, czyli stan naszej klasy, powinien być modyfikowany jedynie przez metody, zaimplementowane w klasie. W ten sposób możemy ograniczyć, ryzyko błędnego użycia klasy. Zanim przejdziemy dalej, zapraszamy do rozwiązania ćwiczeń, które mamy nadzieję, przekonają do tej idei, nie jedną osobę. Zapraszamy!

W następnej lekcji, wykonamy nasz pierwszy mini-projekt, a mianowicie napiszemy aplikację, obsługującą nasze notatki. Postaramy się, użyć i połączyć, jak najwięcej z kursu Python dla początkujących, jak i z części kursu, Python, NIE tylko dla początkujących, w trakcie którego jesteśmy Zapraszamy!

Ćwiczenia

Ćwiczenie 1: Wspomnieliśmy krótko, że nie tylko zmienne, mogą być prywatne, ale również metody w klasie. Pozostając w tematyce naszego samochodu.

Jak możemy zaimplementować w nim automatyczną skrzynię biegów, tak aby opcja zmiany biegów nie była dostępna, po za klasą, ale biegi przełączały się automatycznie wraz ze zmianą prędkości? oczywiście z zachowaniem obecnych funkcji zmiany biegów, które mają w sobie całą logikę.

Ćwiczenie 2: Należy utworzyć, klasę ‚budynek’, która posiada funkcję wejścia do budynku przez osobę, wyjścia z budynku pojedynczej osoby oraz sprawdzenia czy budynek jest pusty. Nie ma natomiast możliwości sprawdzenia ile osób się w nim znajduje.

Rozwiązanie 1: Należy pamiętać, że jest to tylko przykładowe rozwiązanie. Zdecydowaliśmy się w nim zmieniać biegi w metodzie ‚przyśpiesz()’ oraz ‚hamuj()’, natomiast, metody ‚biegNastępny()’ oraz ‚biegPoprzedni()’, zrobić prywatnymi.

class samochód:
    
    def __init__(self):
        
        self.__silnik = False
        self.__bieg = 0
        self.__prędkość= 0
        
    def uruchom(self):
        self.__silnik = True
    
    def wyłącz(self):
        self.__silnik = False
    
    # ukrywamy metody zmiany biegu, aby nie można było zmienić biegu ręcznie
    
    def __biegNastępny(self):
        if self.__bieg <= 6: self.__bieg += 1; print(self.__bieg)
    
    def __biegPoprzedni(self):
        if self.__bieg >= 0: self.__bieg -= 1; print(self.__bieg)
            
    def przyspiesz(self):
        if self.__silnik == True: # usuneliśmy również warunek sprawdzający bieg
            self.__prędkość += 10;
            print(self.__prędkość)
            
            # zmieniamy bieg na wyższy
    
            self.__biegNastępny()
        
    def hamuj(self):
        if self.__prędkość >= 10: self.__prędkość -= 10
        else: self.__prędkość = 0
        print(self.__prędkość)

        # zmieniamy bieg na niższy
            
        self.__biegPoprzedni()
 
            
car = samochód()
car.uruchom()
car.przyspiesz()
car.przyspiesz()
car.przyspiesz()
car.hamuj()
car.hamuj()
car.hamuj()
car.wyłącz()

Rozwiązanie 2:

class budynek:
    
    __ilośćOsób = 0
    
    def weszła(self):
        self.__ilośćOsób +=1
        
    def wyszła(self):
        self.__ilośćOsób -=1
        
    def czyPusty(self):
        if self.__ilośćOsób > 0: return False
        else: return True
    
b1 = budynek()
b1.weszła()
print(b1.czyPusty())
b1.wyszła()
print(b1.czyPusty())

Python, NIE tylko dla początkujących

  1. Wstęp do kursu
  2. Moduły i pakiety
  3. Programowanie obiektowe – wstęp
  4. Programowanie obiektowe – dziedziczenie
  5. Programowanie obiektowe – hermetyzacja <– bieżąca lekcja
  6. Mini projekt – Organizer
  7. Funkcje rekurencyjne w Python
  8. Pisanie skryptów w Python
  9. Mini projekt – tajny agent, generator haseł
  10. *args oraz **kwargs
  11. Dekoratory w Python
  12. Mini projekt – tajny agent – kontakty
  13. Odwzorowanie list
  14. Podsumowanie oraz dalsze kroki