Python - Primjeri objektno orijentisanih programa


U ovome primjeru radićemo dva primjera objektno orijentisanih programa u jeziku Python. Prvi primjer je objektno orijentisana verzija programa za računanje indeksa tjelesne mase. Drugi primjer je program za unos podatka pomoću grafičkog korisničkog interfejsa, koji je razvijem korišćenjem klasa iz biblioteke tkinter.



Klasa IndeksTjelesneMase

Prvo se u posebnom modulu definiše odgovarajuća klasa Indeks Tjelesne Mase, koja se zatim koristi za izradu objektno orijentisanog programa. Objektno orijentisani razvoj bavi se povezivanjem podataka i operacija nad njima u jednistvene strukture: objekte. Rješenje ovoga programa bi se moglo uraditi modularizacijom, tako što bi se definisala funkcija IndeksTM(visina, težina) i višestruko koristila u programima. No, ako bi trebalo koristiti dodatne podatke o osobama (npr. ime i starost), promjenjljive bi se kreirale na različitim mestima u programima, a sama funkcija bi se trebala značajno promjeniti. Pogodniji način realizacije programa je smještanje i funkcija i podataka u jednu međusobno povezanu strukturu, klasu IndeksTM, koja je prikazana na sljedećem UML dijagramu:





Svi podaci neke osobe smještaju se u polja podataka ime, starost, visina i tezina. Inicijalizator klase kreira instancu klase, objekt IndeksTM, za zadano ime, starost, težinu i visinu jedne osobe. Metodi klase računaju indeks tjelesne mase i vraćaju status osobe (Normalna težina, Povećana težina, itd.). Modul IndeksTM sadrži istoimenu klasu, koja računa indeks tjelesne mase i na osnovu njega određuje status tjelesne mase osobe:

"""
    Modul IndeksTM
    Klasa za računanje indeksa i određivanje statusa tjelesne mase osobe
"""
class IndeksTM:
    # Inicijalizator
    def __init__(self, ime, starost, tezina, visina):
        self.__ime = ime
        self.__starost = starost
        self.__tezina = tezina
        self.__visina = visina

    def getIndeksTM(self): # Indeks tjelesne mase
        ind = self.__tezina /((self.__visina/100)**2)
        return round(ind * 100) / 100

    def getStatus(self): # Opis statusa
        ind = self.getIndeksTM()
        if ind < 18.5:
            return "Nedovoljna težina"
        elif ind < 25:
            return "Normalna težina"
        elif ind < 30:
            return "Povećana težina"
        else:
            return "Gojaznost"

    def getIme(self):
        return self.__ime # Skrivena promjenjljiva

    def getStarost(self):
        return self.__starost # Skrivena promjenjljiva

    def getTezina(self):
        return self.__tezina # Skrivena promjenjljiva

    def getVisina(self):
        return self.__visina # Skrivena promjenjljiva

Objektno orijentisani pristup objedinjava dobre strane proceduralnog programiranja (modularnost) i mogućnost integracije podataka i svih operacija nad njima u objekte. Pogodno definisanu klasu programi mogu višestruko upotrebljavati. Modul IndeksTM može se koristiti na isti način u različitim programima, npr:

from indeks_tjelesne_mase import IndeksTM
   ...
ind1 = IndeksTM("Jovana Jovanović", 18, 66, 178)
print("Indeks tjelesne mase za", ind1.getIme(), "je", ind1.getIndeksTM(), ind1.getStatus())
    ...
ind2 = IndeksTM("Nikola Nikolić", 50, 98, 178)
print("Indeks tjelesne mase za", ind2.getIme(), "je", ind2.getIndeksTM(), ind2.getStatus())
    ...

Program IndeksTjelesneMase (objektno orijentisana verzija)

Objektno orjentisan program za računanje indeksa i određivanje statusa tjelesne mase neke osobe može se praktično realizivati pomoću dva modula, IndeksTM i glavnog programa. Glavni program učitava osnovne podatke o osobi, a zatim računa i prikazuje indeks i status pomoću metoda klase getIndeksTM() i getStatus() iz modula IndeksTM:

"""
    Program računa indeks tjelesne mase osobe i štampa status (normalna, povećana, ...)
"""
from indeks_tjelesne_mase import IndeksTM

# Unos imena, starosti, tjelesne težine i visine osobe
ime = input("Unesite ime i prezime osobe: ")
starost = int(input("Unesite starost osobe (godina): "))
težina = float(input("Unesite tjelesnu težinu (kg): "))
visina = float(input("Unesite visinu (cm): "))

# Kreiranje objekta klase IndeksTM
indeks = IndeksTM(ime, starost, težina, visina)

# Računanje indeksa tjelesne mase i ispis rezultata
print("Indeks tjelesne mase za", indeks.getIme(), "je", indeks.getIndeksTM(), indeks.getStatus())

Rezultat izvršavanja programa za računanje indeksa i statusa tjelesne mase osobe je:

Unesite ime i prezime osobe: Marko Marković
Unesite starost osobe (godina): 18
Unesite tjelesnu težinu (kg): 66
Unesite visinu (cm): 178
Indeks tjelesne mase za Marko Marković je 20.83 

Normalna težina


Osnovni elementi biblioteke Tkinter

Programska biblioteka tkinter (od Tk interface) sadrži klase, koje se koriste za kreiranje grafičkog korisničkog interfejsa (Graphical User Interface, GUI) programa u jeziku Python. U sljedećoj tabeli prikazane su klase ove biblioteke koje su osnovni elementi grafičkog korisničkog interfejsa:

Klasa (widget) Opis
Button Taster koji se koristi za izvršavanje metoda
Canvas Komponenta za crtanje slika i grafikona
Checkbutton Polje za izbor
Entry Polje za unos teksta (text box)
Frame Kontajner ostalih vizuelnih komponenti
Label Prikazuje tekst ili sliku
Menu Panel za implementaciju menija (pull-down/popup)
Menubutton Komponenta za implementaciju tastera menija (pull-down)
Message Prikaz teksta koji se prilagođava obliku prozora
Radiobutton Polje za izbor koje briše druga povezana polja za izbor
Text Prikaz formatiranog teksta, koji može da sadrži slike

Osim formi za unos podataka, biblioteka tkinter omogućava kreiranje meni sistema i prikaz slika i grafikona. Primjer jednostavnog grafičkog interfejsa, koji se sastoji od grafičkog prozora u kome su dva vizuelna objekta, tekstualna poruka i grafički taster (button), kao što je prikazano na sljedećoj slici, može se jednostavno kreirati:





Jednostavni interfejs sa slike može se kreirati pomoću svega nekoliko naredbi:

from tkinter import * # uvoz svih imena iz biblioteke

prozor = Tk() # Kreiranje grafičkog prozora
# Kreiranje grafičkih elemenata za prozor

tekst = Label(prozor, text="Volim učiti Python uz IT TUTORIJALE") # tekst
taster = Button(prozor, text="Kreni s učenjem!") # taster

# Raspoređivanje elemenata u prozoru (redovi/kolone)
tekst.pack() # Smeštanje teksta u objekt prozor
taster.pack() # Smeštanje tastera u objekt prozor
prozor.mainloop()# Osnovna petlja za obradu događaja

U primjeru metod Tk() kreira prozor (window), koji predstavlja osnovnu klasu (kontejner) za ostale vizuelne komponente (widgets). Osnovna petlja obrađuje događaje objekta prozor, npr. pritisak na taster, pomeranje i zatvaranje prozora.


Program za unos podatka preko grafičkog interfejsa

Korisnička klasa koja predstavlja grafičku formu za unos podatka, može se predstaviti u UML notaciji kao na sljedećoj slici:





Klasa ima jedno polje za unos tekstualnog podatka (tipa string) i dva metoda, inicijalizator i metod obradiTaster(), koji može npr. da omogući preuzimanje podatka iz grafičkog interfejsa i unesenu vrijednost dodjeli nekoj promjenjljivoj programa. Pogodno je klasu definisati u posebnom modulu, npr. forma_za_unos, jer se kasnije može višestruko koristiti:

from tkinter import * # Sva imena iz biblioteke

class FormaZaUnos:
    def __init__(self):
        prozor = Tk() # Kreiranje grafičkog prozora
        prozor.title("Forma za unos") # Naslov prozora
        # Kreiranje i dodavanje okvira 1 u prozor
        frame1 = Frame(prozor)
        frame1.pack()

        # Dodavanje teksta i polja za unos u frame1
        tekst = Label(frame1, text="Unesite svoje ime: ")
        self.ime = StringVar() # def. tipa vrijednosti
        poljeIme = Entry(frame1, textvariable = self.ime)

        # Dodavanje tastera za potvrdu unosa u frame1
        tasterGetIme = Button(frame1, text="Potvrdi", command=self.obradiTaster)
        tekst.grid(row = 1, column = 1)
        poljeIme.grid(row = 1, column = 2)
        tasterGetIme.grid(row = 1, column = 3)

        prozor.mainloop() # Petlja za obradu događaja
        
    def obradiTaster(self):
        print("Unijeli ste vrijednost: " + self.ime.get())

Program koji koristi ovako definisanu formu za unos omogućava da se podatak unese putem grafičkog umjesto konzolnog interfejsa i može imati oblik:

""" 
    Jednostavna forma za unos podataka.
    Klasa FormaZaUnos kreira formu za unos podataka u grafičkom prozoru.
    Forma se sastoji od polja za unos imena i tastera za potvrdu unosa.
"""
from forma_za_unos import FormaZaUnos

# Kreiranje grafičkog interfejsa i unos podataka
forma = FormaZaUnos()

print("Putem forme uneseno je ime: ",
forma.ime.get())

Pokretanjem programa kreira se novi grafički prozor u kome se prikazuje forma za unos podataka, kao što je prikazano na slici. Forma omogućava unos i editovanje tekstualne vrijednosti u grafičkom polju i završetak unosa pomoću tastera Potvrdi.





Rezultat unosa program provjerava ispisom poruka na konzolni izlaz:

Unijeli ste vrijednost: Marko
Putem forme uneseno je ime: Marko

Poruke prikazuju sadržaj polja forme ime nakon potvrde unosa podatka tasterom Potvrdi; prva poruka je iz metoda obradiTaster(), a druga iz glavnog programa. Ovo je veoma jednostavan primjer forme za unos samo jednog, tekstualnog podatka. Forme za unos mogu da sadrže veći broj različitih elemenata koji su navedeni u prethodnoj tabeli, čime se omogućava ne samo direktni unos podataka, već i unos jedne ili više ponuđenih vrijednosti.