Pierwsze koty za płoty – Python – obiekty i klasy

devkot.pl 1 rok temu

Język programowania Python nie służy tylko i wyłącznie do tworzenia prostych skryptów. W poprzednim artykule: Pierwsze koty za płoty – Python – pierwsza aplikacja, miałeś okazję napisać swój pierwszy skrypt, kompletnie od początku. W ramach tego artykułu postaram Ci się wyjaśnić główne koncepcje związane z programowaniem zorientowanym obiektowo oraz jego podstawowe budulce takie jak klasy i obiekty.

Czym adekwatnie są te klasy i obiekty?

Klasy i obiekty są składowymi najpopularniejszego paradygmatu programowania, czyli obiektowego. Pozwala on na tworzenie systemu składającego się z wielu elementów, które ze sobą współpracują, zachowując ich prostotę. Wiem, na ten moment może wydawać się to niezrozumiałe, ale w dalszej części tego artykułu postaram Ci się to wyjaśnić, ale najpierw przedstawię trochę teorii, którą następnie będziesz miał okazję sprawdzić w przedstawionych przykładach.

Programowanie zorientowane obiektowo (klasy i obiekty)

Programowanie zorientowane obiektowo to paradygmat programowania, który zakłada traktowanie elementów programów jako obiektów. Główne koncepcje paradygmatu obiektowego to:
enkapsulacja – polega na ukrywaniu szczegółów implementacyjnych obiektów i udostępnianiu jedynie niezbędnych funkcjonalności
dziedziczenie – pozwala na tworzenie hierarchii klas, w których określone klasy dziedziczą pewne cechy po innych klasach
polimorfizm – umożliwia przesyłanie tych samych wiadomości do różnych obiektów i uzyskanie różnych wyników
abstrakcja – polega na wyodrębnianiu cech charakterystycznych dla danej klasy i tworzeniu ogólnych definicji
interfejsy – pozwala na zdefiniowanie metod, które muszą być zaimplementowane przez klasy, które je implementują.

Koncepcje te pozwalają na tworzenie bardziej elastycznych, skalowalnych i łatwiejszych w obsłudze programów. Programowanie obiektowe jest stosowane w różnego rodzaju programach, w tym w systemach informatycznych, aplikacjach internetowych oraz grach komputerowych.

Klasy

Klasa i obiekt to dwa najważniejsze pojęcia programowania obiektowego. Klasa według definicji jest szablonem, który definiuje postać obiektu. Określa ona adekwatności, czyli zmienne, które są zapisywane do pamięci komputera oraz powiązane z konkretną instancją obiektu. W skład klas wchodzą również metody, czyli są to funkcje (zachowania), które dany obiekt może wykonać.
Klasy są pojęciami abstrakcyjnymi. Przyjrzymy się ich analogii do prawdziwego świata. Co jest pierwszą rzeczą, która przychodzi Ci na myśl, po usłyszeniu słowa kot? Obstawiam, iż kojarzy Ci się konkretny kot, być może Twój, być może sąsiada lub kogokolwiek innego. Przyjmijmy, iż po usłyszeniu słowa kot na myśl przychodzi Ci takie zwierzę:

Powyższy kot w odniesieniu do programowania jest obiektem klasy kot. Sama idea klasy służy do przedstawienia wycinka rzeczywistości/pojęcia w kontekście programistycznym. Przyjmijmy koty posiadają jakieś imię(name), rasę(breed) oraz jakieś typowe kocie zachowania, jak np. to iż można go zawołać (wykorzystując jego imię) oraz może wykonywać typowo kocie rzeczy czyli np. miauczeć, drapać, pić mleko itp. W ten sposób opisaliśmy pojęcie jakim jest kot, bez odnoszenia tego do konkretnego zwierzęcia. Wykorzystajmy teraz tą wiedzę do zdefiniowania klasy Cat:

class Cat: breed = 'Cat' def __init__(self, name): self.name = name def call(self): print(self.name) def meow(self): print('Typing...') print('Meow')

Powyższy kod opisuje kota w sposób abstrakcyjny. Określa jego zmienne takie jak imię oraz rasę (póki co ustawiona na wartość Cat) oraz typowe kocie zachowania. Jest to próba ogólnego opisu tego czym są koty i jak się zachowują. Konkretny żyjący kot jest tak naprawdę obiektem utworzonym z wykorzystaniem konkretnego szablonu, jakim jest klasa. Przejdźmy teraz do analizy kodu klasy w celu wyjaśnienia jej konkretnych elementów składowych.

Właściwości

Jak możesz zaobserwować na powyższym przykładzie definiowanie klasy zaczyna się od słowa kluczowego „class”, a następnie od nazwy klasy. Klasa składa się z adekwatności, w tym przypadku są nimi zmienne breed(rasa) oraz name(imię). W powyższym przykładzie możesz także zobaczyć, iż kot udostępnia dwie metody(zachowania). Pierwsza z nich pozwala zawołać kota, natomiast druga pozwala na wywołanie typowego dla devkotów zachowania czyli pisania na klawiaturze.

Metody

Metody klas, podobnie jak funkcje mogą przyjmować argumenty, czyli zmienne przekazywane do obiektu w celu wykonania jakiegoś zachowania. Specyficzną rzeczą dla Pythona jest to, iż definiując funkcje, jako pierwszy argument należy wskazać zmienną, do której zostanie przekazany obiekt, na którym wywoływane jest dane zachowanie. W przykładowym kodzie jest to zmienna self. Następnie można zdefiniować dodatkowe zmienne, które będą konieczne do wykonania zachowania.
Metoda __init__ jest tzw. konstruktorem obiektu, prościej mówiąc służy ona do utworzenia nowej instancji obiektu danej klasy. Efektem jej wywołania jest utworzenie oraz zapisanie w pamięci komputera obiektu danej klasy.
Ważnym elementem, który należy zapamiętać jest to, iż klasa sama w sobie jest tylko wzorcem, który opisuje obiekty. Podczas działania aplikacji wykorzystuje się obiekty, które zostały stworzone według wzoru przedstawionego przez klasę.

Obiekty

Skoro wiesz już czym są klasy i iż są one bardzo mocno powiązane z obiektami, to teraz należy zrozumieć czym jest ten cały obiekt. Obiekt jest to główny element programowania zorientowanego obiektowo. Jest on tworzony według konkretnego szablonu (klasy), która opisuje adekwatności oraz metody przez niego udostępniane. Nawiązując do przykładu żywego kota, w świecie programowania można przyjąć, iż jest on obiektem klasy kot o konkretnej rasie oraz imieniu. Przyjrzyjmy się teraz w jaki sposób możemy stworzyć swojego nowego kota dzięki języka Python:

class Cat: breed = 'Cat' def __init__(self, name): self.name = name def call(self): print(self.name) def meow(self): print('Typing...') print('Meow') cat = Cat('Kociak') print(cat.breed) cat.call() cat.meow()

W powyższym przykładzie utworzyliśmy nową instancje obiektu klasy Cat oraz przypisaliśmy ją do zmiennej o nazwie cat. Dzięki przypisaniu obiektu do zmiennej, możemy dostać się do składowych konkretnej klasy tj. do rasy kota oraz możemy uruchomić jego konkretne zachowania takie jak call oraz meow. Rezultatem uruchomienia takiego skryptu będzie wypisanie na oknie konsoli poniższych informacji:

Przeanalizujmy linię 14-17 przykładowego kodu. Pierwsza z nich odpowiada za wywołania konstruktora klasy Cat oraz przypisaniu imienia konkretnego konkretnego kota. Następna linijka wypisuje na oknie konsoli jego imię oraz w kolejnych liniach wywołujemy jego konkretne zachowania, takie jak: zawołaj i zamiaucz.

Wszystko jasne, ale co w przypadku gdy chcę mieć więcej niż 1 kota? Nic trudnego należy utworzyć kolejną instancję obiektu i przypisać ją do nowej zmiennej:

class Cat: breed = 'Cat' def __init__(self, name): self.name = name def call(self): print(self.name) def meow(self): print('Typing...') print('Meow') cat = Cat('Kociak') print(cat.breed) cat.call() cat.meow() devkot = Cat('Devkot') cat.call()

W powyższym przykładzie w linii 19 została utworzona nowa instancja klasy Cat z imieniem Devkot, dzięki czemu masz 2 niezależne koty żyjące w pamięci Twojego komputera, sic! Aby lepiej zasymulować interakcje między kotami przyjmijmy iż mogą się ona nawzajem podrapać.

class Cat: breed = 'Cat' def __init__(self, name): self.name = name def call(self): print(self.name) def scratch(self, cat): print(f'Cat: {self.name} scratched cat: {cat.name}') def meow(self): print('Typing...') print('Meow') cat = Cat('Kociak') devkot = Cat('Devkot') cat.scratch(devkot)

Efektem uruchomienia tego kodu będzie:

Jak widzisz na powyższym zrzucie ekranu kot Kociak podrapał kota Devkot. W ten oto sposób udało się nam stworzyć zachowania, które angażują inny obiekt do wykonania konkretnego zachowania. Wykorzystaliśmy argumenty przekazywane do metody, dzięki których wskazaliśmy, który kot został podrapany.

Obiekty - jak są przechowywane w pamięci komputera

Zastanawiasz się jak to się dzieje, iż komputer był w stanie przekazać konkretny obiekt jako argument do metody innego obiektu. Jest to możliwe dzięki temu jak jest zbudowana pamięć w komputerze oraz dzięki temu, iż zmienne, które przechowują obiekt tak naprawdę przechowują adres do miejsca w pamięci, gdzie ten obiekt się znajduje, czyli przechowują referencję do obiektu.

Referencja w Pythonie to sposób, w jaki program odwołuje się do konkretnych obiektów w pamięci. Kiedy tworzysz nowy obiekt, Python rezerwuje dla niego miejsce w pamięci komputera. Referencja zawiera informację o adresie w pamięci, gdzie znajduje się ten obiekt. Zapisanie referencji do zmiennej oznacza, iż ta zmienna wskazuje na dany obiekt.

Dzięki temu mechanizmowi, gdy przekazujesz obiekt do innej metody lub funkcji tak naprawdę informujesz ją, gdzie w pamięci komputera powinien jej szukać, czyli przekazujesz jej adres.

Więcej na temat organizacji pamięci w komputerach możesz przeczytać w ramach tego artykułu: STOS I STERTA. KONFRONTACJA STRUKTUR DANYCH. Szczerze polecam zapoznać się z tym artykułem.

Mam nadzieję, iż ilość teorii Ciebie nie przeraziła, ale to na dziś tyle. W ramach kolejnych artykułów skupimy się na pojęciach stricte związanych ze światem programowania obiekt ego takimi jak: dziedziczenie, polimorfizm, interfejsy oraz przyjrzymy się ogólnym zasadom tworzenia dobrego i jakościowego kodu.

Do zobaczenia w kolejnym artykule!

Idź do oryginalnego materiału