Python - Objektno orjentisano programiranje OOP


Objektno orijentirano programiranje

Python je programski jezik sa više paradigmi. Podržava različite pristupe programiranju. Jedan od popularnih pristupa rješavanju problema programiranja je stvaranje objekata. Ovo je poznato kao objektno orijentirano programiranje (OOP). Objekt ima dvije karakteristike:

  1. Atributi
  2. Ponašanje

Pogledajmo primjer. Papagaj može biti objekt, jer ima sljedeća svojstva:

  • Ime, starost, boja kao atributi
  • Pjevanje, ples kao ponašanje

Koncept OOP-a u Pythonu fokusira se na stvaranje koda za višekratnu upotrebu. Ovaj koncept je poznat i pod nazivom DRY (Don't Repeat Yourself). U Pythonu, koncept OOP-a slijedi neke osnovne principe:


Klase (Class)

Klasa je nacrt objekta. O klasi možemo razmišljati kao o skici papige s naljepnicama. Sadrži sve detalje o imenu, bojama, veličini itd. Na osnovu ovih opisa možemo proučavati papagaja. Ovdje je papagaj objekt. Primjer za klasu papagaja može se napisati kao:

class Parrot:
    pass

Ovdje koristimo ključnu riječ class da definišemo praznu klasu Parrot. Iz klase gradimo instance. Instanca je specifični objekt kreiran iz određene klase.


Objekti (Object)

Objekt (instanca) je instancija klase. Kada se definiše klasa, definiše se samo opis objekta. Zbog toga nije dodijeljena memorija ili pohrana. Primjer za objekt klase papagaja (parrot) može se napisati kao:

obj = Parrot()

Ovdje je obj objekt klase Parrot. Pretpostavimo da imamo detalje o papagajima. Sada ćemo pokazati kako se gradi klasa i objekti papiga.


Primjer 1: Stvaranje klase i objekta u Pythonu

class Parrot:

    # class atribut
    species = "ptica"

    # instance atribut
    def __init__(self, name, age):
        self.name = name
        self.age = age

# instanca Parrot class
blu = Parrot("Blu", 10)
woo = Parrot("Woo", 15)

# pristupanje klasi (class) atributa
print("Blu je {}".format(blu.__class__.species))
print("Woo je takođe {}".format(woo.__class__.species))

# pristupanje atributima instance
print("{} is {} years old".format( blu.name, blu.age))
print("{} is {} years old".format( woo.name, woo.age))

U gore navedenom programu stvorili smo klasu s imenom Parrot. Zatim definišemo atribute. Atributi su karakteristika objekta. Ti su atributi definisani unutar __init__ metode klase. To je metoda inicijalizatora koja se prvo pokreće čim se kreira objekt. Zatim kreiramo instance klase Parrot. Ovdje su blu i woo reference (vrijednost) na naše nove objekte.

Atributu klase možemo pristupiti koristeći __class __.species. Atributi klase su isti za sve instance klase. Slično tome, atributima instance pristupamo koristeći blu.name i blu.age. Međutim, atributi instance su različiti za svaku instancu klase. Da biste saznali više o klasama i objektima, posjetite lekciju Python klase i objekte



Metode

Metode su funkcije definisane unutar tijela klase. Koriste se za definisanje ponašanja objekta.


Primjer 2: Stvaranje metoda u Pythonu

class Parrot:
    
    # atributi instance
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    # metoda instance
    def sing(self, song):
        return "{} sings {}".format(self.name, song)

    def dance(self):
        return "{} sada pleše".format(self.name)

# instanciranje objekta
blu = Parrot("Blu", 10)

# pozovanje naše metode instance
print(blu.sing("'Srećan'"))
print(blu.dance())

U gornjem programu definišemo dvije metode, tj. sing() i dance(). Oni se nazivaju metodama instance, jer se pozivaju na objektu instance, tj. blu.



Nasljeđivanje (Inheritance)

Nasljeđivanje je način stvaranja nove klase za korištenje detalja postojeće klase bez njenog mijenjanja. Novoformirana klasa je izvedena klasa (ili podređena klasa). Slično tome, postojeća klasa je osnovna klasa (ili roditeljska klasa).


Primjer 3: Upotreba nasljeđivanja u Pythonu

# roditeljska klasa
class Bird:
    
    def __init__(self):
        print("Ptica je spremna")

    def whoisThis(self):
        print("Ptica")

    def swim(self):
        print("Plivaj brže")

# dijete (child class) klasa
class Penguin(Bird):

    def __init__(self):
        # Pozivanje super() funkcije
        super().__init__()
        print("Pingvin je spreman")

    def whoisThis(self):
        print("Pingvin")

    def run(self):
        print("Trči brže")

peggy = Penguin()
peggy.whoisThis()
peggy.swim()
peggy.run()

U gornjem programu stvorili smo dvije klase, tj. bird (roditeljska klasa) i Penguin (dječja klasa - child class). Podređena klasa nasljeđuje funkcije roditeljske klase. To možemo vidjeti iz metode swim().

Opet, podređena klasa je promijenila ponašanje roditeljske klase. To možemo vidjeti iz metode whoisThis(). Nadalje, proširujemo funkcije nadređene klase, stvaranjem nove metode run().

Pored toga, koristimo funkciju super() unutar metode __init __(). To nam omogućava da pokrenemo metodu __init __() roditeljske klase unutar podređene klase.



Enkapsulacija (Encapsulation)

Koristeći OOP u Pythonu, možemo ograničiti pristup metodama i varijablama. To sprječava izravnu modifikaciju podataka koja se naziva enkapsulacija. U Pythonu označavamo privatne atribute koristeći donju crtu kao prefiks, tj. pojedinačno _ ili dvostruko __.


Primjer 4: Enkapsulacija podataka u Pythonu

class Computer:

    def __init__(self):
        self.__maxprice = 900

    def sell(self):
        print("Prodajna cijena: {}".format(self.__maxprice))

    def setMaxPrice(self, price):
        self.__maxprice = price

c = Computer()
c.sell()

# promjena cijene
c.__maxprice = 1000
c.sell()

# korištenje setter funkcije
c.setMaxPrice(1000)
c.sell()

U navedenom programu definisali smo računarsku klasu. Koristili smo metodu __init__() za čuvanje maksimalne prodajne cijene računara. Pokušali smo izmijeniti cijenu. Međutim, ne možemo je promijeniti, jer Python __maxprice tretira kao privatne atribute. Kao što je prikazano, za promjenu vrijednosti moramo koristiti funkciju SetMaxPrice() koja uzima cijenu kao parametar.



Polimorfizam (Polymorphism)

Polimorfizam je sposobnost (u OOP-u) da koristi zajednički interfejs za više oblika (tipovi podataka). Pretpostavimo da trebamo obojiti oblik, postoji više mogućnosti oblika (pravougaonik, kvadrat, krug). Međutim, mogli bismo koristiti istu metodu za bojanje bilo kog oblika. Ovaj koncept naziva se polimorfizam.


Primjer 5: Korištenje polimorfizma u Pythonu

class Parrot:

    def fly(self):
        print("Papagaj može letjeti")
    
    def swim(self):
        print("Papagaj ne zna plivati")

class Penguin:

    def fly(self):
        print("Pingvin ne može letjeti")
    
    def swim(self):
        print("Pingvin zna plivati")

# zajednički interfejs
def flying_test(bird):
    bird.fly()

# instanciranje objekta
blu = Parrot()
peggy = Penguin()

# dodavanje objekta
flying_test(blu)
flying_test(peggy)

U navedenom programu definisali smo dvije klase Parrot i Penguin. Svaka od njih ima zajedničku metodu fly(). Međutim, njihove funkcije su različite. Da bismo koristili polimorfizam, stvorili smo zajednički interfejs, tj. funkciju flying_test() koja uzima bilo koji objekt i poziva objektnu metodu fly(). Dakle, kada smo prošli blu i peggy objekte u funkciji flying_test() je djelovao efikasno.



Ključne tačke koje treba zapamtiti:

  • Objektno orijentirano programiranje čini program lakim za razumijevanje i učinkovitim.
  • Budući da je klasa dijeljiva, kod se može ponovo koristiti.
  • Podaci su sigurni i abstraktni.
  • Polimorfizam omogućava isti interfejs za različite objekte, tako da programeri mogu pisati efikasan kod.