Daleko bilo da je ovo sve što treba da znaš o toj temi. "Najbolji način da se započne put od 10000 kilometara je da se napravi prvi korak" - kineska poslovica (naravno original razdaljinu nije merio kilometrima). Shvati ovo upravo kao pokušaj da se taj prvi korak napravi što bezbolnije.
Pretpostavlja se da si programirao na Pascal-u, C-u ili nekom "običnom" procedurelnom jeziku i da si osetio da ti nešto nedostaje. To "nešto" je viši nivo apstrakcije. OOP nije toliko tehnika programiranja, koliko način razmišljanja. Naravno najbolje je da jezik direktno podržava OOP - to omogućava da razmišljaš direktno koristeći njegova sredstva. Ali čak i na ne-objektnim jezicima, OO razmišljanje se itekako isplati.
Parafraziraću Bjarne Stroustrup-a, tvorca C++-a: Mali program (recimo 1000 linija) može da se napiše u bilo čemu, bilo kako. Ako si dovoljno vešt, na kraju ćeš ga naterati da radi. Ali u velikom programu, ako se nisi pridržavao "lepog programiranja" i koristio odgovarajuće tehnike - naročito OOP, nove greške će se pojavljivati jednako brzo kao što ispravljaš stare.
Razlog tome je što svaki deo programa zavisi od gomile drugih, ali te zavisnosti su toliko zamršene i neintuitivne da ih čak i tvorac teško prati. Kada promeniš jedan deo programa, ne možeš lako da sagledaš na čega sve u stvari to utiče. Naravno, valjanim procedurelnim programiranjem može se prilično dobro modularizovati program i izdvojiti ponovo upotrebljiv kod, ali ako tako radiš - onda već počinješ da misliš na OOP način. Ono što ti nedostaje je bolji način da organizuješ gomilu procedura koje si kroz praksu napisao i da ih bolje povežeš sa strukturama podataka kojima manipulišu.
Vratimo se malo na fakultet, definiciji tipa podataka: "Tip podataka je uređena dvojka čiji je prvi element skup svih dozvoljenih vrednosti za taj tip, a drugi element skup svih operacija koje nad tim vrednostima možemo izvršiti.". Tip je dvojstvo podataka i operacija nad njima.
Ako znaš šta je tip, onda znaš i šta je osnovni pojam OOP-a: klasa. Naime, klasa je ništa drugo do jezičko sredstvo da se definiše tip podataka. Iskompajliraj ovo u glavi: klasa je, znači, način da se u programskom jeziku procedure i funkcije eksplicitno povežu za strukturu podataka. Logično pitanje sledi: "Ali ja sam u parametre procedure mogao da stavim bilo šta - uključujući i strukturu podataka koja me interesuje - na taj način sam povezivao tip sa njegovim operacijama. U čemu je razlika?". Razlika je u (podebljanoj) reči "eksplicitno". U OOP-u procedure koje pripadaju klasi su na više načina "posebne" i sa njima se mogu raditi stvari nemoguće za "smrtne" procedure. Takve procedure se nazivaju metodi.
Pa, šta će ti to u životu? Evo četiri dobra razloga:
Pod jedan, ako imaš klasu Trougao i metod Crtaj (koji joj pripada i vrši iscrtavanje trougla), ništa te ne sprečava da napraviš i klasu Kvadrat koja takođe ima metod Crtaj (koji crta kvadrat). Iako se isto zovu, to su različiti metodi. Znači, štedimo imena i izbegavamo konflikte. Moduli (u Pascal-u su to unit-i) se mogu upotrebiti u ovu svrhu, a neki jezici pružaju i posebne mehanizme u borbi za dodeljivanje logičnih imena (na pr. C++ prostori imena - namespaces ili prilično unapređeni moduli Module-2). Ipak moduli su često preglomazni za ovoj zadatak, pogotovo ako su (kao na Pascal-u) vezani za fizičko skladištenje sorsa - fajlove. U Moduli-2, na primer, moduli mogu da sadrže i podmodule za koje je tačno definisano šta daju spoljašnjem svetu i šta iz njega vide, ali to pomalo liči na gađanje muve maljem od dve tone. Ovako, ako imaš promenljivu t klase Trougao i promenljivu k klase Kvadrat, trougao crtaš sa t.Crtaj a kvadrat sa k.Crtaj - šta ćeš jednostavnije?
A sada dođoh i do pojma objekat. Prosto, objekat je promenljiva neke klase. Drugi naziv je instanca ("primerak"). Klasa je definicija tipa, objekat je konkretan primerak klase. Na pr. kada kažemo da promenljiva t ima tip (klasu) Trougao, drugi način da kažemo to isto je: t je objekat tipa Trougao. Ma, da ne davim, t i k iz prethodnog pasusa su objekti.
Pod dva, svaka klasa može da sakrije ono što želi. Ako imaš pomoćno parče koda koje pozivaju samo metodi unutar klase, napravićeš privatan metod, nevidljiv spolja. Ako si pisao veće programe, ovo si opet radio preko modula (unit-a) sakrivanjem u implementation sekciju (cpp fajl kod C++-a). Međutim, opet rizikuješ da se zatrpaš gomilom modula od kojih svaki koristi svaki i koji su međusobno isprepletani više nego što bi zaista želeo. Ovakvo sakrivanje zove se enkapsulacija. Neki jezici, na pr. C++ i novije verzije Jave, čak mogu da imaju klase unutar drugih klasa, koje opet mogu da budu privatne.
Do sada, uz dovoljno samodiscipline, mogao si da preživiš koristeći klasična sredstva lepog programiranja - pre svega module. Sada ide nešto što se jednostavno ne može uraditi bez OOP-a.
Pod tri i najvažnije: Nasleđivanje je način da već postojeću "roditeljsku" klasu proširiš ili izmeniš i napraviš novu "klasu dete" koja ostaje povezana sa roditeljskom. Ovo je ključ onoga što englezi zovu code-reusability (ponovna iskoristivost koda). Ako već imaš klasu koja radi neznatno manje od onoga što ti treba, zašto ne iskoristiti taj već napisani kod i samo dopisati ono što ti treba? Naravno copy-and-paste programiranje može učiniti da veoma lako "iskoristiš" ono što je već napisano. Ali time dobijaš dve komadeške koda za koje samo ti znaš da bi trebalo da rade istu stvar - dok ne zaboraviš. Sada zamisli da si našao grešku u prvoj kopiji - to znači da treba treba da protrčiš kroz sve ostale i napraviš identične ispravke. Zamisli žurku kada imaš desetak kopija! Samo da te upozorim: nije neobično da ozbiljne biblioteke klasa (kakav je Delphi-jev VCL) imaju i po nekoliko desetina nivoa nasleđivanja. Kakav bi to bio haos da je u pitanju prosto kopiranje istog koda! A efikasnosti se još nismo ni dotakli.
Međutim, kada se sa napravi pravo nasleđivanje, ako promeniš kod u roditeljskoj klasi, automatski si promenio i svu decu. Sa druge strane, u većini jezika, decu možeš dodavati bez rekompajliranja roditelja, obično čak ni ceo izvorni kod nije potreban - dosta je samo interfejs (deklaracija klasa/ metoda bez definicije). Naravno, nema višestrukog kompajliranja (interpretiranja) jednog te istog, pa je sve brže i zauzima manje mesta. Do sada sam govorio uglavnom o metodima, ali nasleđivanjem možeš dodati i nova polja, no o-tom-po-tom (još ne znaš ni kako jedna klasa izgleda kad se napiše u konkretnom programskom jeziku).
Četvrto, tesno povezano sa nasleđivanjem: polimorfizam. Ovo je nešto o čega se početnici u OOP-u najlakše spotaknu, pa nemoj da se sekiraš ako ne svariš sve odmah. Kada naslediš neku klasu, na fizičkom nivou joj dodaš/promeniš metode ili članove (polja), ali na logičkom nivou, ti samo praviš novu vrstu te klase. A'jmo sad, iz neba pa u rebra, pa ko shvati, razumeće: dete jeste roditelj. To znači: tamo gde stoji roditelj, mogu da stavim i dete, naprosto zato što dete sadrži sve što i roditelj (iako verovatno i nešto preko toga). Uoči da obrnuto ne važi. Naime, roditelj nije dete - dete sadrži i nešto što roditelj nema, pa roditelja ne možemo da stavimo svuda gde možemo dete jer će nešto da nam zafali.
A sada suština: čak iako dete stavimo mesto roditelja, ono i dalje ostaje dete. Ako pozovemo metod koji postoji i u roditelju i u detetu, koja od ove dve verzije metoda će biti pozvana zavisi od toga da li smo u vreme izvršavanja stavili roditelja ili dete. Ako smo stavili dete, biće pozvan metod deteta. Na pr. bez obzira što je u vreme kompajliranja parametar neke procedure deklarisan kao roditelj, u vreme izvršavanja možemo u njega da stavimo dete, i ono će nastaviti da se ponaša kao dete.
Inače, ovo je razlog za korišćenje pokazivača u OOP-u.
Dakle suština polimorfizma je: Objekti se isto koriste ali se različito - u skladu sa svojom konkretnom klasom - ponašaju. U vreme kompajliranja nemamo način da odredimo koji će konkretni objekti to biti, ali u vreme izvršavanja za svaki objekat se pozivaju metode klase kojoj pripada, a ne roditeljske klase koja je deklarisana u vreme kompajliranja.
Da opet pozovem u pomoć Bjarne Stroustrup-a: Programski jezik ima dva aspekta: jedan omogućava da mašini narediš šta da radi, a drugi predstavlja konceptualni alat koga ti sam koristiš u razmišljanju o tome kako rešiti problem. Principi koje sam izložio ne samo da postoje u svakom pristojnom objektnom jeziku, već predstavljaju jako dobar način apstrakcije. Više se nećeš gušiti u detaljima dijagrama toga, već ćeš se izmaći, pogledati problem sa visine i početi da ga raščlanjuješ na objekte koji u njemu učestvuje. Te objekte ćeš razvrstati u logične "stablaste" strukture - hijererhije nasleđivanja.
http://www.elitesecurity.org/tema/13240