SITNA CREVCA<>
012017<><>

Kako postati programer (4): Funkcije, klase itd.

Razlike u klasama

Deo kôda koji se često ponavlja izdvaja se u funkcije. Objektno orijentisano programiranje se zasniva na klasama.

Do sada ste naučili kako izgledaju neki najprostiji konzolni programi. Pre svega ćemo dopuniti stečeno znanje iz prethodnog broja, ali se zbog obima tekstova nadamo da i sami možete da uočite neka pravila programiranja koja nismo eksplicitno pokazali.

Trebalo bi da je „u hodu” postalo jasno da se program sastoji od niza komandi, koje se u većini jezika završavaju tačkom i zarezom. Ovaj niz komandi se naziva izraz (expression). Ceo izraz ne mora da bude u istom redu, što znači da možete da na pola izraza lupate taster ’enter’ koliko god hoćete. Slično tome, kôd možete da kucate u istom redu i posle „;” simbola. To se retko radi, jer obično dovodi do neuredno napisanog, teško preglednog kôda, osim u nekim pogodnim situacijama kao što je uvođenje (deklarisanje) promenljivih u program.

Druga uočljiva karakteristika je što koristimo vitičaste zagrade za označavanje posebnog programskog bloka, kao što je telo FOR petlje ili IF uslova. Međutim, ukoliko nema vitičastih zagrada onda se izvršava samo prvi naredni red. Danas mnogi to smatraju lošom praksom i insistiraju da se i taj jedan red uokviri zagradama. Javascript je karakterističan zato što on sam dodaje „;” gde misli da je potrebno, tako da je preporuka da levu vitičastu zagradu uvek pišete u nastavku prethodnog izraza tj. nemojte je prebacivati u novi red. U suprotnom, Javascript može dodati tačku zarez pre vitičaste zagrade i na taj način pokvariti kôd. Python je po ovom pitanju nešto drugačiji i umesto zagrada gleda koliko ste uvukli red tj. kolika je tabulacija.

Komentari se mogu pisati između /* i */ oznaka, što je zgodno kada ostavljate duže poruke, jer ne morate da pišete dve kose crte u svakom redu.

Postoji cela plejada osnovnih tipova promenljivih koje nismo pomenuli, donekle različitih u zavisnosti od jezika. Uglavnom su to varijacije u opsegu celih i decimalnih brojeva. Na primer, integer i float su tipovi manjeg opsega od tipova long i double. Tip char predstavlja samo jedan karatker, bool/boolean samo vrednost ’tačno’ ili ’netačno’. To je važno ako vaš program mora da barata sa velikim brojevima ili kada je potrebna veća matematička preciznost. Ukoliko vam toliko veliki brojevi nisu potrebni, onda je bolje da koristite tipove manjeg opsega, uglavnom zbog optimizacije kôda. Na primer, C++ ima tipove kao što su short, signed ili unsigned, ali o tome nije potrebno da vodimo toliko računa na ovom nivou. Opet, JavaScript, na primer, poznaje samo jedan tip brojeva, a to je broj sa decimalnim zarezom (koji se koristi i za cele brojeve i za decimalne brojeve).

Operatori „++” i „--” povećavaju broj za plus ili minus jedan. Pošto oni mogu da se pišu ispred ili iza promenljive, potrebno je voditi računa prilikom pisanja (ili čitanja tuđeg) kôda. Razlika je u prioritetu tog operatora u okviru programske naredbe (pogledajte primer). I dok se nekad podrazumevalo da dobar programer ovu razliku lako prepozna, Swift jezik je ovaj operator izbacio iz upotrebe, jer su moderne tendencije da se piše što čitljiviji kôd (umesto toga se piše izraz oblika × = × + 1). Zanimljivo je da je Swift tek nedavno niz karaktera nazvao String. Do tada je naziv bio NTString, po inicijalima NextStep kompanije Stiva Džobsa koju je osnovao kada je otišao iz Applea 1985. godine.

U nekim listinzima nećemo pisati ceo kôd, niti pisati primere za više jezika kada su razlike minimalne. Podrazumeva se da listing unosite u funkciji main (Java, C++ i NetBeans IDE) ili u konzoli (JavaScript, Chrome developer tools, F12). Sledi primer za C++. Za Java varijantu koristite boolean, a za JavaScript tipove promenljivih zamenite sa var. Ukoliko pišete direktno u Chrome konzoli, novi red dobijate sa ’shift+enter’.

----------------------- C++ -----------------------

//pisanje u istom redu

int a, b, c = 50; float t = 32.123;

//pisanje u vise redova, u ovom slucaju necitko

bool

    brojProcitan

  = true;

;;;;;; //gomila praznih izraza

{} //prazan blok

Iskazi, izrazi, logički operatori

Izraz (statement) je termin kojim se u programiranju označava cela linija kôda, dok iskaz (expression) može biti i samostalni deo kôda i deo nekog izraza, a suština je u tome što se on izračunava kao tačan ili netačan. Iskazi se često koriste u kontroli toka. Na primer, deo u zagradi IF uslova je iskaz, na osnovu koga će se kôd unutar uslova izvršiti ili ne. Cela linija kôda sa naredbom IF, uključujući iskaz u zagradi, je izraz.

U kontroli toka važnu ulogu imaju logički operatori negacije, „i” i „ili” (obično se označavaju sa „!”, „&&” i „||”). Sa njima se može napisati složenija provera tačnosti nekog iskaza. Iskaz se u programskim jezicima najčešće smatra netačnim ukoliko je false ili „0”, dok je u ostalim slučajevima tačan. U jezicima C++ i JavaScript, broj ili brojevna promenljiva (int) se automatski konvertuje u bool vrednost (tačno ili netačno), dok u Javi to nije moguće već u startu mora da se koristi boolean vrednost.

----------------------- C++ -----------------------

int a = 0; bool d = false;

/* Provera sa true se podrazumeva i ne mora se inace pisati */

if (a == true)

  cout << "blabla";//Ova linija se ne bi izvrsila

if (5)

  cout << "blabla"; // Ova linija bi se izvrsila

if (d = true)

  cout << "blabla";

/* U zagradi je dodela a ne provera:

d postaje true pa se onda proverava tacnost izraza.

Ovaj uslov je legalan za Javu, ali prethodna dva nisu. */

int b = 10;

bool c = true;

bool brojProcitan = false;

/* iskaz u zagradi ce biti tacan, jer negiramo negativnu vrednost */

if (!brojProcitan)

  cout << "zasto nije?"; // kod se izvrsava

cout << ("ovaj red se uvek ispisuje");

if (b++ > 10);

/* Uslov nije ispunjen posto b nije veće od 10. b se poveca za jedan tek posle provere. */

/* Varijanta sa ++b prvo povecava b pa tek onda ispituje uslov, koji bi bio ispunjen. */

if (b || c); if (b && c);    

// LEVO: Provera da li je makar jedan uslov tacan.

// Oba su tacna, pa je uslov ispunjen

// DESNO: Provera da li su oba uslova tacna.

// Jesu, pa je uslov ispunjen

// NAPOMENA: ne radi u Javi jer b nije boolean

for ( ;false || c; ) {

  // Petlja samo sa uslovom

  /* Uslo bi se u beskonacnu petlju jer imamo

  jednu tacnu vrednost: c */

}

Za kraj ovog segmenta primetite kako smo u FOR petlji napisali samo uslov njenog izvršavanja. Iako se sa njom može obaviti sve što će nam ikada biti potrebno, za ovakve prostije petlje ponekad se koristi DO..WHILE ili WHILE..DO sintaksa. Svaka petlja se može prekinuti usred kôda u vitičastim zagradama komandom BREAK. Sledi primer DO..WHILE petlje u slučaju kada bi mnogo zgodnije bilo koristiti FOR petlju (promenljiva koja diktira uslov izvršavanja petlje je mogla da se inicijalizuje i menja u naredbi FOR uslova).

for (int i +0; brojevi[i]==12; i++)

---------------------- Java ----------------------

int[] brojevi = {1, 5, 12, 122};

  int i = 0;

  while (i < brojevi.length) {

    if (brojevi[i] == 12) {

      break;

    }

    i++;

  }

Funkcije

Funkcije su jedan od osnovnih programskih koncepata i morate ih savršeno znati. Deo kôda koji napišete unutar funkcije možete da koristite bilo gde u programu, tako što pozovete tu funkciju. Funkciju pozivate kada u kôd ukucate njeno ime i dve male zagrade, koje mogu biti prazne ili da sadrže dodatne parametre koji se prosleđuju funkciji.

U prošlom broju smo napisali prostu igru za dva igrača koji pogađaju brojeve između jedan i deset. Sada ćete napraviti funkciju koja proverava da li je broj koji je igrač uneo zaista između jedan i deset, i koja ispisuje poruku ukoliko taj broj nije tačan. Istu funkciju možete da pozovete kada drugi igrač unosi broj i tako izbegnete dupliranje kôda. Pazite da se u primeru Java jezika ime klase poklapa sa nazivom fajla i da nazivi paketa i import naredbe budu isti.

---------------------- Java ----------------------

package primer;

import java.io.Console;

import java.util.Scanner;//za unos podataka

public class Primer {

  public static void main(String[] args) {

    Scanner sc = new Scanner(System.in);

    int broj1, broj2;

    do {

      System.out.println("Unesi broj igraca 1");

      broj1 = sc.nextInt();

    } while (!ispravanBroj(broj1));

    do {

      System.out.println("Unesi broj igraca 2");

      broj2 = sc.nextInt();

    } while (!ispravanBroj(broj2));

  }

  static public boolean ispravanBroj(int broj) {

    if (broj > 0 && broj < 11) {

      return true;

    }

    System.out.println("broj mora da bude");

    System.out.println("izmedju 1 i 10");

    return false;

  }

}

-------------------- JavaScript -------------------

var broj1, broj2;

do {

  broj1 = prompt("Broj igraca 1");

} while (!ispravanBroj(broj1))

do {

  broj2 = prompt("Broj igraca 2");

} while (!ispravanBroj(broj2))

function ispravanBroj(broj) {

  if (broj > 0 && broj < 11) {

    return true;

  }

  console.log("morate uneti broj izmedju 1 i 10");

  return false;

}

----------------------- C++ -----------------------

#include <iostream>

using namespace std;

bool ispravanBroj(int broj) {

if (broj > 0 && broj < 11)

  return true;

cout << "broj mora da bude izmedju 1 i 10!";

return false;

}

int main(int argc, char** argv) {

int broj1, broj2;

do {

  cout << "Unesi broj igraca 1 \n";

  cin >> broj1;

} while (!ispravanBroj(broj1));

do {

  cout << "Unesi broj igraca 2 \n";

  cin >> broj2;

} while (!ispravanBroj(broj2));

}

Funkcija koju smo napisali naziva se ispravanBroj. Ime funkcije obično treba da se izabere tako da se lepo slaže sa kôdom odakle je pozivate. Pošto hoćete da proverite da li je broj unet po pravilima igre, onda će se naziv funkcije lepo uklopiti u programski kôd koji će se čitati kao: „ako je brojIspravan”. Funkcije koje vrše ovakvu proveru se na engleskom jeziku, na kojem ćete najčešće pisati vaš program, obično nazivaju sa početnim „is”, na primer „isNumberOkay”.

Funkcija ima naziv, nula ili više vrednosti koje prima i opciono, vrednost koju daje na kraju svog izvršavanja, ili programerski rečeno vrednost koju „vraća” (u stvari zadajemo tip vrednosti, da li je broj ili string ili nešto drugo). Ako pogledate našu funkciju, vrednost koju funkcija vraća se piše ispred njenog naziva, a jedan ili više parametara koje prima pišu se u zagradi nakon naziva. Zatim se u vitičastim zagradama piše telo funkcije koji čine sve komande (izrazi) koje će se izvršiti po pozivu te funkcije. Za sada zanemarite izraze public i static.

U kôdu smo funkciju pozvali i kao argument (parametar) prosledili joj broj koji je izabrao igrač. Na taj način je taj broj vidljiv u telu funkcije. Funkcija proverava da li je broj ispravan i ako jeste, vraća vednost tačno na ono mesto u kôdu sa kog je pozvana. To mesto je uslov IF naredbe, pa na osnovu toga šta je funkcija odgovorila zavisiće i to da li je uslov ispunjen.

Kada pozivate funkciju iz kôda, morate da pazite koji je tip podataka koji joj prosleđujete. Ne možete da kao parametar stavite neki string ako ste u deklaraciji funkcije napisali da prihvata int. U Javascriptu uopšte ne pišete tipove, JavaScript će sam da se postara o njima. Imajte u vidu da promenljiva koju prosledite funkciji ne mora da ima isti naziv i u samoj funkciji. vaš je izbor kako ćete nazvati parametar, ali često se ipak koriste isti nazivi.

Funkcija ne mora ništa da vraća ili prima. Kada je pozovete iz kôda ona će izvršiti šta se nalazi u njenom telu i posle toga će se glavni kôd nastaviti dalje. Obično se piše void kada funkcija ne vraća vrednost (u Javascriptu se u tom slučaju ništa ni ne piše). Evo primera funkcija bez ikakvih parametara i sa više parametara. U Javi funkciju napišite unutar glavne klase, a u C++-u iznad funkcije main.

---------------------- Java ----------------------

static void funkcija1(){};

static int funkcija2(int br1, String tekst1, String tekst2){return 0;};

-------------------- JavaScript -------------------

function primer1(){};

function primer2(br1, tekst1, tekst2){return 0};

Klase, nasleđivanje, overrajdovanje

Kada govorimo o objektno orijentisanom programiranju (OOP), govorimo o klasama. Kao što neka promenljiva može da bude broj ili string, tako može da bude i klasa. Takva promenljiva se zove objekat. Za JavaScript smatramo da nije od presudnog značaja da pokažemo princip klasa, pa ćemo u narednom broju pogledati šta je to bitnije kada pričamo o JavaScriptu.

Klasu zamislite kao neki kontejner koji u sebi sadrži promenljive i funkcije na jednom mestu. Vi ćete napisati klasu koja će predstavljati podatke o čitaocima „Sveta kompjutera”, kao i specijalizovaniju klasu koja opisuje čitaoca koji najviše voli da igra avanturističke igre. Da začinimo stvari, svaku od tih klasa ćemo napisati u posebnom fajlu, dakle van fajla sa funkcijom main u kojem počinje izvršavanje programa. Tako se u praksi najčešće i radi. Klase dodajte u program tako što kliknete desnim dugmetom na koren strukture u kojoj se nalazi glavni fajl, u levom delu NetBeansa i izaberete New Class.

---------------------- Java ----------------------

//Fajl Primer.java

package primer;

public class Primer {

public static void main(String[] args) {

  Avanturista Pera = new Avanturista();

  Pera.brojGodina = 25;

  Pera.ime = "Pera";

  Pera.omiljenaRubrika = "Test Play";

  Pera.omiljenaAvantura = "The Dig";

  Pera.podaciCitaoca();

}

}

//Fajl SKCitalac.java

package primer;

public class SKCitalac {

String ime;

int brojGodina;

String omiljenaRubrika;

void podaciCitaoca() {

  System.out.println("ime: " + ime);

  System.out.println("brojGodina: " +

  brojGodina);

  System.out.println("omiljenaRubrika: " +

  omiljenaRubrika);

}

}

//Fajl Avanturista.java

package primer;

public class Avanturista extends SKCitalac {

String omiljenaAvantura;

void podaciCitaoca() {

  super.podaciCitaoca();

  System.out.println("omiljenaAvantura: " +

  omiljenaAvantura);

}

}

----------------------- C++ -----------------------

//main.cpp

#include <iostream>

#include "Avanturista.h"

using namespace std;

int main(int argc, char** argv) {

Avanturista Pera;

Pera.brojGodina = 25;

Pera.ime = "Pera";

Pera.omiljenaRubrika = "Test Play";

Pera.omiljenaAvantura = "The Dig";

Pera.podaciCitaoca();

}

//SKCitalac.h

#include <string>

class SKCitalac {

public:

std::string ime;

int brojGodina;

std::string omiljenaRubrika;

void podaciCitaoca();

}

//SKCitalac.cpp

#include "SKCitalac.h"

#include <iostream>

using namespace std;

void SKCitalac::podaciCitaoca() {  

cout << "ime: " << ime << "\n";

cout << "broj godina: " << brojGodina << "\n";

cout << "omiljenaRubrika: " << omiljenaRubrika << "\n";

}

//Avanturista.h

#include "SKCitalac.h"

#include <iostream>

class Avanturista : public SKCitalac {

public:

std::string omiljenaAvantura;

void podaciCitaoca();

}

//Avanturista.cpp

#include "Avanturista.h"

void Avanturista::podaciCitaoca() {

SKCitalac::podaciCitaoca();

std::cout << "Omiljena avantura: " << omiljenaAvantura << "\n";

}

Naša klasa, „SKČitalac”, ima promenljive „ime”, „broj godina” i „omiljena rubrika”. Promenljive unutar klase se u nekim jezicima nazivaju polja, u nekim svojstva (properties). Pored promenljivih, ova klasa ima i funkciju koja na konzoli ispisuje podatke o čitaocu (ova funkcija nema parametre ni vrednost koju vraća). U prethodnom delu teksta ste mogli videti šta su funkcije, a funkcija koja je u klasi obično se naziva metod (method).

Jedna od najvažnijih osobina OOP-a je nasleđivanje klasa. Klasa „Avanturista” uvodi novu promenljivu „omiljenaAvantura”. Mi smo napisali kôd tako da ova klasa nasleđuje klasu „SKČitalac”, tako da nasleđuje sve njene promenljive! Isto važi i za funkcije (tj. metode). U prevodu, ne moramo ispočetka da pišemo ove članove klase.

Međutim, metoda koja ima zadatak da ispiše sve promenljive na konzolu, u našoj izvedenoj klasi ne ispisuje novouvedenu promenljivu „omiljenaAvantura”, prosto jer ona nije postojala u baznoj iliti roditeljskoj klasi. Nema problema, napisaćemo ponovo taj metod, reći ćemo mu da ponovi sve što je radio u baznoj klasi, i dodatno napisati izraz za ispisivanje omiljene avanture. Ovo preuređivanje metode u izvedenoj klasi zove se overrajdovanje (override).

Zamislite da su nam za program bile potrebne i klase čitaoca koji igraju strategije, logičke igre... Na isti način bismo mogli da proširimo osnovnu klasu i napravimo nove izvedene klase „Strateg” i „Logičar”. Nasleđivanjem štedimo vreme i pišemo manje kôda. Metodi iz bazne klase se može pristupiti komandom super u izvedenoj klasi (u Javi), odnosno pisanjem bazne klase i njene metode razdvojenih dvotačkom (C++), kao u našem primeru. Primetite kako je NetBeans automatski označio da je funkcija overrajdovana ili da klasa ima podklasu.

Pošto ste definisali ove klase, red je da ih iskoristite u kôdu tj. da neka promenljiva bude objekat neke od njih. U glavnom delu kôda napravite nekog imaginarnog čitaoca „Žiku” koji je čitalac našeg časopisa. „Žika” objekat sada poseduje sve članove svoje klase, kojima pristupate tako što nakon njegovog imena napišete tačku i ime promenljive ili funkcije. Dodelite neke vrednosti „Žikinim” promenljivama, a onda pozovite njegovu metodu koja će da ispiše sve njegove promenljive na konzolu (nećemo previše voditi računa kada upotrebljavamo reč funkcija, metod, polje itd.).

Nadamo se da neće biti previše problema da istražite priloženi kôd. Kôd slobodno prepišite preko onoga što će NetBeans automatski da kreira. Sada kada znate šta su metode, biće jasniji kôd iz prošlog broja u kojem ste dobili informaciju o dužini niza. Nizovi se u Javi i Javascriptu tretiraju kao objekti, i jedna od promenljivih niza kojoj možete da pristupite je njegova dužina.

Organizacija fajlova

Klase se u Javi pišu u standardnom .Java fajlu. Ako pogledate kako je NetBeans organizovao projekat, najvažnije je da vidite da smo fajlove u kojima su naše klase smestili u isti folder gde je i fajl sa funkcijom main. Folderi se u Javi nazivaju paketima, i pošto su svi naši fajlovi unutar istog „paketa”, sve klase su odmah vidljive u glavnom fajlu. U suprotnom, morali bismo da ih uvedemo koristeći komandu import i njihovu putanju.

Jezik C++ je nešto komplikovaniji, jer se obično pišu dva fajla za jednu klasu. Videćete da je NetBeans automatski napravio „.h” i „.cpp” fajlove za svaku klasu. Fajlovi sa „.h” ekstenzijom služe za deklaraciju klasa. Fajlovi sa „.cpp” ekstenzijom služe za njihovo definisanje. Prosto rečeno, u „.cpp” fajlu ćete napisati i telo funkcije koja se nalazi u klasi, dok ćete u „.h” fajlu napisati samo njeno ime. U fajlu gde je funkcija main, klase postaju dostupne kada u komandi include navedete „.h” fajl.

Na kraju

Kada pogledate sav kôd koji smo do sada pisali, trebalo bi da vam bude očiglednija struktura početnog fajla kada pišemo kôd. Program pisan jezikom C++ počinje unutar, sada znamo, funkcije main koja prima neke parametre (nije sada ni bitno toliko šta oni znače). Java program takođe počinje unutar funkcije (metode) main, koja se nalazi u početnoj klasi. U Javi sve što pišete mora biti unutar neke klase. Kada gledamo C++, on može da ima i kôd van klase. Pogledajte samo primer prvih funkcija u tekstu.

Nadamo se da su sada jasnije i naredbe import i include u raznim primerima do sada. Otkud ti fajlovi koji su „inkludovani” i „importovani”? Ti fajlovi (biblioteke) dolaze sa programskim jezikom i kako ne bismo opteretili kôd, oni su podeljeni po funkcijama koje pružaju korisniku. Ne postoji lak način da znate sve biblioteke koji dolaze sa jezikom, već je potrebno malo iščitavanja dokumentacije i pretrage na Internetu. Vremenom ćete naučiti koje se to biblioteke najčešće koriste i u čemu sve mogu da vam pomognu.

Ako pogledate C++, primetićete da koristimo liniju „using namespace std”. Sve biblioteke koje smo „inkludovali” u primerima su C++ biblioteke u tzv. „std” namespaceu (prostoru imena). To je način na koji C++ rešava problem da se nazivi funkcija ili klasa iz različitih biblioteka ne „sudaraju” u slučaju da su isto nazvane. Mi naš kôd nismo „zamotali” ni u kakav namespace, pa se on nalazi u tzv. globalnom namespaceu. Da ste izostavili pisanje „using namespace std”, onda biste morali da ispred svake komande tog namespacea pišete „std::”, na primer „std::string”. Java nema ovakav sistem provere, pa u slučaju preklapanja naziva potrebno je da pišete punu „putanju” paketa i njegove klase. No, ovo možete detaljnije proučiti samostalno.

U sledećem broju ćemo pogledati druge važne osobine objektno orijentisanog programiranja, ali i krenuti dalje.

Ognjen POPOVIĆ

 
 NOVE TEHNOLOGIJE
Otkrića koja mogu da promene svet

 TRŽIŠTE
Microsoftova hardverska ofanziva

 NA LICU MESTA
Epson prezentacija
Kaspersky prezentacija
DJI prezentacija
Nordeus Hackathon 6
IKT Start-up
Dodela nagrada mts app konkursa

 KOMPJUTERI I FILM
The Great Wall
xXx
Filmovi, ukratko

 SITNA CREVCA
Kako postati programer (4): Funkcije, klase itd.
Šta mislite o ovom tekstu?

 VREMENSKA MAŠINA
SCSI, HAL 9000 i sonda na Titanu

 PRST NA ČELO
Na Zapadu ništa dobro
Home / Novi brojArhiva • Opšte temeInternetTest driveTest runPD kutakCeDetekaWWW vodič • Svet igara
Svet kompjutera Copyright © 1984-2018. Politika a.d. • RedakcijaKontaktSaradnjaOglasiPretplata • Help • English
SKWeb 3.22
Opšte teme
Internet
Test Drive
Test Run
PD kutak
CeDeteka
WWW vodič
Svet igara



Naslovna stranaPrethodni brojeviOpšte informacijeKontaktOglašavanjePomoćInfo in English

Svet kompjutera