02.11.2014 Views

Proceduralni jezici - FESB

Proceduralni jezici - FESB

Proceduralni jezici - FESB

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

Programski <strong>jezici</strong><br />

2009<br />

1. Povijest programskih jezika<br />

2. Što definira programski jezik:<br />

Leksička struktura<br />

Sintaksa<br />

Semantika<br />

3. Elementi s kojima manipuliramo programskim jezikom:<br />

tipovi i klase,<br />

konstante i varijable,<br />

funkcije i procedure,<br />

kontrolne strukture i iznimke<br />

4. Temeljne paradigme za podjelu programskih jezika:<br />

Strojni i asemblerski jezik<br />

<strong>Proceduralni</strong> (imperativni) <strong>jezici</strong> (C, Pascal, Fortran)<br />

Objektno orijentirani <strong>jezici</strong> (C++, Java, C#)<br />

Funkcionalni <strong>jezici</strong> (Lisp, Sheme, ML, Haskell)<br />

Logički orijentirani <strong>jezici</strong> (Prolog)<br />

Vizualno programiranje<br />

Učit ćemo barem jedan jezik iz svake grupe.<br />

1


Smjerovi razvoja programskih jezika<br />

U početku, ... programi su pisani u strojnom kodu, sekvence bitova, obično u heksadecimalnoj notaciji, predstavljali su i<br />

naredbe i podatke u računalu.<br />

Primjer:<br />

34020005<br />

0000000c<br />

3c011001<br />

Koji čudak moţe pisati programe na ovaj način (bilo ih je nekoliko)<br />

Prvi simbolički jezik - Asembler<br />

Umjesto binarnih nizova pišu se simbolička imena naredbi i memorijskih lokacija<br />

Primjer:<br />

mov eax,5<br />

push eax<br />

call absvalue<br />

sub esp, 4<br />

Ovo je lakše razumjeti od binarnih sekvenci, ali i dalje se mora programirati na vrlo niskoj razini - direktno se manipulira s<br />

memorijom i vanjskim ureĎajima.<br />

2


U asembleru:<br />

o Postoji samo jedan tip podataka - niz bajta.<br />

o Kontrolne strukture su: uvjetni i bezuvjetni skokovi.<br />

o Imena (varijabli i labela) su globalni objekti<br />

o Potprogrami se realiziraju kao prosti skokovi na mjesto izvršenja programa.<br />

o Nije poznat mehanizam prijenosa argumenata funkcije.<br />

Fortran (Formula Translator)<br />

Prvi pravi programski jezik, razvijen 50-tih godina.<br />

Primjer:<br />

sum = 0<br />

do 10 i=1,100<br />

10 sum = sum + a(i)<br />

Korak naprijed u programiranju:<br />

Programiranje postaje ―problemski orijentirano‖, a manje je ―strojno orijentirano.‖<br />

Uvode se kontrolne strukture: "if" - selekcija i "do"-petlja .<br />

Uvodi se mehanizam prijenosa argumenata potprograma<br />

Razlikuju se funkcije i procedure<br />

Novije varijante su: Fortran 77, Fortran 90 i HPF (High Performance Fortran).<br />

3


Cobol (Common Business Oriented Language)<br />

Jezik za poslovne aplikacije s bazama podataka. Razvijen početkom 60-tih godina.<br />

Primjer:<br />

multiply i by 3 giving j.<br />

move j to k.<br />

write line1 after advancing<br />

1 lines.<br />

Cobol je:<br />

o Prvi standardizirani programski jezik.<br />

o Još i danas se koristi u komercijalnim aplikacijama.<br />

o Jezik s dosta riječi, pogodan za proste programere.<br />

o Prvi puta otvara diskusiju o potrebi pisanja razumljivog kôda<br />

4


BASIC<br />

BASIC (Beginner’s All-purpose Symbolic Instruction Code) je kreiran na DARTMOUTH College od John Kemeny i<br />

Thomas Kurtz-a 1964. godine kao jezik za ne-profesionalce. To je bio prvi pravi interpreter.<br />

Varijable su zapisivane jednim slovom ili slovom iza kojeg slijede znamenke.<br />

Ne koristi se eksplicitne deklaracije varijabli.<br />

Varijable mogu biti numeričke vrijednosti ili stringovi.<br />

Svakoj naredbi prethodi numerička oznaka, koja se koristi kao oznaka za skokove u programu.<br />

Primjer:<br />

10 REM A SAMPLE BASIC PROGRAM FOR SORTING ARRAY A<br />

20 DIM A(100)<br />

30 FOR I = 1 TO 100<br />

40 INPUT A(I)<br />

50 NEXT I<br />

60 FOR I = 1 TO 100<br />

70 J = I<br />

80 FOR K = J+1 TO 100<br />

90 IF A(K) < A(J) THEN 130<br />

100 T = A(I)<br />

110 A(I) = A(J)<br />

120 A(J) = T<br />

130 NEXT K<br />

140 NEXT I<br />

150 STOP<br />

160 END<br />

Današnje verzije BASIC jezika, primjerice Visual Basic, nemaju značajnije sličnosti s ovim jezikom.<br />

5


Algol 60 (Algorithmic Language)<br />

Razvijen 1960. kao prvi jezik koji je potpuno pogodan za strukturalno programiranje. Direktni je prethodnik jezika Pascal,<br />

C, C++ i Java.<br />

Primjer:<br />

real procedure cheb(x,n);<br />

value x,n;<br />

real x; integer n;<br />

cheb := if n = 0 then 1<br />

else if n = 1 then x<br />

else 2 * x * cheb(x,n-1) - cheb(x,n-2);<br />

Algol uvodi u programske jezika danas standardne elemente:<br />

o Blokovi s lokalnim deklaracijama<br />

o UgnijeţĎene deklaracije i kontrolne strukture.<br />

o Prijenos parametara potprograma,<br />

o Potprogrami mogu biti rekurzivni.<br />

Iako dobro koncipiran, nije šire prihvaćen jer:<br />

o Nema standardizirani pristup I/O ureĎajima.<br />

o IBM je preferirao razvoj Fortrana i PL/I.<br />

6


Lisp (List Processing Language)<br />

Lisp je razvijen početkom 60-tih godina. U njemu se odstupa od proceduralne (imperativne) osnove programskih jezika, a<br />

uvode se elementi funkcionalnog programiranja<br />

Primjer Lisp interpretera:<br />

>(+ 1 2 5)<br />

8<br />

>((lambda (x) (* x x)) 10)<br />

100<br />

Karakterisike Lispa:<br />

o Program i podaci se predstavljaju kao liste u prefiksnoj notaciji<br />

o (+ 9 8 7) znači: izraz kojem se rezultat dobije zbrajanjem brojeva 8,8 i 7<br />

o Ne postoji deklaracija tipova varijabli<br />

o Tipovi su svojstva vrijednosti podataka, a ne svojstva varijable ili parametara funkcije.<br />

o Program u toku izvršenja moţe stvarati i izvršavati funkcije i izraze<br />

o Vrši se automatsko alociranje memorije - koristi se "garbage collection" mehanizam<br />

Pri razvoju jezika prvi put je razvijena i definirana formalna semantika - njome se precizno odreĎuje značenja<br />

programa.<br />

Slijednik Lispa je jezik Scheme koji uvodi neke elemente iz Algola (lokalni doseg).<br />

7


Simula 67 (Simulation Algol)<br />

Simula 67 je prvi objektni jezik - uvodi se definiciju klasa<br />

Primjer:<br />

Class Rectangle (Width, Height);<br />

Real Width, Height;<br />

Boolean Procedure IsSquare;<br />

IsSquare := Width=Height;<br />

End of Rectangle;<br />

Simula 67 proširuje Algol s:<br />

definicija klase i proširene klase.<br />

Definicija objekata i garbage collector.<br />

ADA<br />

ADA - jezik je sredinom 70-tih razvijen za U.S. Dept. of Defense<br />

Ističe vaţnost modularnog programiranja<br />

8


C i C++<br />

C je razvijen početkom 70-tih godina, a C++ sredinom 80-tih godina. Oba jezika su prihvaćeni kao temeljni <strong>jezici</strong> za<br />

"performance-critical applications": izradu operativnih sustava i sistemskog softvera.<br />

Omogućuju platform-independent programiranje. (#define leksičke - supstitiucije)<br />

Oba jezika mogu koristiti i početnici i profesionalni programeri, ali to ne znači da su podesni za početno poimanje<br />

programiranja.<br />

To bolje omogućuju Java i C#. Jednostavnost slijedi iz činjenice da ovi <strong>jezici</strong> ne koriste pokazivače.<br />

Java<br />

Jezik Java je razvijen krajem 90-tih, kao jezik za izradu distribuiranih mreţnih programa. Glavne karakteristike su :<br />

Jednostavniji je i čišći jezik od C++, što je ostvareno nauštrb brzine izvršenja programa.<br />

Čisti OO jezik - sve konstrukcije jezika se definiraju unutar klase.<br />

Naglasan na sigurnosti, a ne na brzini.<br />

Potpuna neovisnost o operativnom sustavu.<br />

C#<br />

Vrlo je sličan Javi, ali je nešto bliţi C++ jeziku nego Java.<br />

9


Zašto se istražuju novi programski <strong>jezici</strong>?<br />

1. Znatiželja<br />

Koji drugi oblici jezika mogu biti realizirani?<br />

2. Produktivnost<br />

Standardni proceduralni <strong>jezici</strong> su vrlo zahtjevni kad treba razvijati softver posebne namjene. U tom slučaju je moţda bolje<br />

razviti intepreter za tu posebnu namjenu. Primjerice, jezik Matlab omogućuje jednostavno rješavanje matematičkih<br />

problema.<br />

3. Sigurnost i pouzdanost<br />

I dalje je pitanje sigurnosti izvršenja programa vrlo vaţno pitanje, koje je moţda moţe bolje riješiti u samom programskom<br />

jeziku.<br />

4. Brzina izvršenja<br />

Jezici C i C++ omogućuju najbrţe izvršenje programa na standardnim računalima, meĎutim nisu pogodni za sustave<br />

računala koji rade paralelno ili distributivno.<br />

10


Poželjne karakteristike programskih jezika<br />

Gledano teoretski, kada programski jezik tretiramo kao dio stroja računala, tada su skoro svi programski <strong>jezici</strong> ekvivalentni<br />

i pomoću njih se mogu riješiti svi problemi koje je moguće riješiti računalom (Church –Turing teza). Ipak, <strong>jezici</strong> imaju i<br />

druge, mnogo značajnije funkcije a to je da omoguće apstrakciju, efikasne programe i ugodno programiranje.<br />

Koje svojstva jezika su poţeljna?<br />

Jednostavnost upotrebe jezika.<br />

o Programi trebaju biti jednostavni i razumljivi<br />

o Konstrukcije jezika trebaju biti ortogonalne, tj. da postoji samo jedan način izvršenja.<br />

o Zapis treba biti što bliţi duhu aplikacije koja se programira.<br />

Jezik treba podrţavati apstrakciju.<br />

o Postojeće strukture i operacije trebaju biti dogradive za nove apstraktne strukture.<br />

Jezik treba omogućiti jednostavno testiranje i debagiranje programa.<br />

Poţeljno je imati IDE sa sustavom pomoći, editorom i debagerom.<br />

Poţeljno je da jezik omogućuje portabilnost za različite operativne sustave.<br />

Opći su zahtjevi:<br />

o Brzina izvršenja i mali zahtjevi za memorijom.<br />

o PrevoĎenje brzo i modularno, s pripadnim bibliotekama.<br />

o Komponente jezika trebaju biti "reusable"<br />

11


Programske i jezičke paradigme<br />

Programske jezike dijelimo prema 4 fundamentalna stila - paradigme: proceduralni, objektno orijentirani, funkcionalni i<br />

logički.<br />

<strong>Proceduralni</strong> <strong>jezici</strong><br />

C, Fortran, Pascal, Ada, itd.<br />

Program se izvršava naredbu po naredbu, te očitava i mijenja sadrţaj memorije.<br />

Na isti način radi i procesor koji komunicira s RAM memorijom..<br />

Pitanje: Za segment programa<br />

a = a + 1;<br />

if (a > 10)<br />

b = 10;<br />

else<br />

b = 15;<br />

a = a * b;<br />

Zašto ovaj program pet procesora ne moţe izvršiti pet puta brţe?<br />

Uoči: ovisnost reda izvršenja i vrijednosti varijable.<br />

12


Kod proceduralnih jezika funkcije često iskazuju bočne efekte (side effects)<br />

int global=1;<br />

int Mul(int x) {<br />

global = global *x;<br />

return global;<br />

}<br />

// side effect – bočni efekt na globalnu var.<br />

int main()<br />

{ // Loše je što<br />

cout


Objektno-orijentirani <strong>jezici</strong><br />

C++, Java, C#, Smalltalk, Pizza i Python su objektno-orijentirani <strong>jezici</strong>.<br />

Podaci i funkcije zdruţeno odreĎuju svojstva i aktivnost objekata.<br />

Objekti su aktivni entiteti sa stabilnim stanjem, i sučeljem prema drugim objektima, s kojima se komunicira pomoću poruka<br />

ili metoda.<br />

U definiranju objekata koristi se princip nasljeĎivanja, princip komponiranja objekata i princip zajedničkog sučelja<br />

(interfejsa).<br />

Interface (sučelje) u JAVI ili virtualne funkcije u C++ jeziku odreĎuju način komuniciranja s različitim objektima, što<br />

omogućuje da se programi izvršavaju polimorfno (višeoblično).<br />

C++ takoĎer omogućuje programske tehnike:<br />

o Modularno programiranje kao podrška za „data hidding―<br />

o Generičko programiranje<br />

o Rukovanje iznimkama<br />

U C# i Javi sve mora biti deklarirano unutar klase, čak i Main() funkcija, od koje starta izvršenje programa<br />

14


C++ program<br />

int main()<br />

{<br />

cout


Funkcionalni <strong>jezici</strong><br />

U funkcionalnim <strong>jezici</strong>ma,<br />

procedure (funkcije) su entiteti prve klase<br />

Entiteti prve klase:<br />

Mogu biti pridjeljeni varijablama<br />

Mogu biti argumenti funkcija<br />

Mogu biti vrijednost koju funkcija vraća.<br />

Mogu biti elementi sloţenih struktura podataka.<br />

Lisp, Scheme i ML su "prirodno" funkcionalni <strong>jezici</strong>.<br />

> (define sqr (lambda (x) (* x x)) # varijabla sqr je funkcija(lambda)<br />

> (sqr 10) # apliciraj funkciju sqr na argument 10<br />

> 100 # rezultat je 100<br />

Program sadrţi izraze koji se "evaluiraju".<br />

Dizajn jezika minimizira bočne efekte uključujući i izbjegavanje upotrebe naredbe pridjele vrijednosti.<br />

16


Logički programski <strong>jezici</strong><br />

Prolog je logički programski jezik. U njemu korisnik zapisuje:<br />

o činjenice i<br />

o što program treba obaviti,<br />

o a ne zapisuje se postupak kojim se izvršava program<br />

Ne koristi se klasična kontrola tijeka programa.<br />

Primjer:<br />

inOrder( [] ).<br />

inOrder( [ _ ] ).<br />

inOrder([a,b|c]) :- (a < b),<br />

inOrder([b|c]).<br />

Ovo je kompletni program, kojim se odreĎuje da li je lista ureĎena.<br />

Primjetite da nema deklaracija, varijabli i eksplicitno zadanih petlji.<br />

17


Koncepti iz programskih jezika<br />

Deklaracija / Doseg / Životnost / Povezivanje - statičko/dinamičko<br />

Identifikatori varijabli i funkcija se deklariraju, eksplicitno ili implicitno iz konteksta prve upotrebe.<br />

Deklaracije povezuju (bind) tip i vrstu s identifikatorom. Primjerice<br />

static int var;<br />

int je tip, static je vrsta varijable var.<br />

Svaki identifikator ima doseg (scope ) u programu— to je dio programa u kojem je vidljiv identifikator<br />

Ţivotnost (lifetime) — je vrijeme u kojem identifikator referira memorijski objekt. Obično je ţivotnost povezana s<br />

dosegom identifikatora, tj. objekt traje za vrijeme izvršenja programa iz dosega identifikatora.<br />

Svojstva identifikatora (i objekta koji on predstavlja) se odreĎuju:<br />

1. Tijekom kompiliranja (Compile-time )<br />

Ta svojstva se nazivaju statična i ne mijenjaju se tijekom izvršenja programa<br />

Primjeri: tip varijable ili tijelo funkcije.<br />

2. Tijekom izvršenja (Run-time)<br />

Ta svojstva se nazivaju dinamička i mogu se mijenjati tijekom izvršenja programa.<br />

Primjeri: vrijednost varijable, dinamički alocirani objekti, argumenti funkcije itd.<br />

18


Dinamički alocirane varijable<br />

U C++ se koristi pokazivače i operatore new i delete. Primjerice, dinamički niz od 6 cijelih brojeva formira se naredbom:<br />

int *pa = new int[6]; // C++<br />

Kada nam više ne treba ova varijabla brišemo je iz memorije operatorom delete:<br />

delete [] pa; // C++<br />

U Javi i C# se svi objekti i nizovi formiraju dinamički - primjenom new operatora. Dealociranje memorije ne vrši korisnik<br />

već se vrši automatski pomoću mehanizma "skupljača smeća" (garbage collection). Zbog toga, jer u Javi i C# nema statičkih<br />

nizova i objekata, njihova imena, iako predstavljaju pokazivače, tretiraju se kao reference. To pojednostavljuje zapis<br />

programa na način da se članovima struktura i klasa uvijek pristupa pomoću točka operatora.<br />

class Test // Java program<br />

{<br />

public static void main(String[] args) {<br />

int[] arr = new int[6];<br />

for (int i = 0; i < arr.length; i++)<br />

arr[i] = i * i;<br />

for (int i = 0; i < arr.length; i++)<br />

System.out.println("arr[" + i + "] = " + arr[i]);<br />

}<br />

}<br />

19


U Javi i C# svi objekti se stvaraju dinamički<br />

class A<br />

{<br />

public void F() { System.out.println("A.F"); }<br />

}<br />

class Test<br />

{<br />

public static void main(String[] args) {<br />

A b = new A(); // dinamički alocirani objekt b<br />

b.F();<br />

// članovima se pristupa pomoću točka operatora<br />

} // iako b stvarno predstavlja pokazivač<br />

}<br />

20


Blok struktuirani <strong>jezici</strong><br />

Algol 60, Pascal, C, C++, Java.<br />

Identifikatori mogu imati lokalni i globalni doseg.<br />

Deklaracije mogu biti lokalne - unutar klase ili bloka.<br />

Ugnjeţdeni blokovi imaju različiti doseg. Identifikatoru se pridjeljuje leksički najbliža deklaracija.<br />

Povezivanje identifikatora i deklaracije je obično statično (ili leksičko), ali su moguća i dinamička povezivanja (npr.<br />

pretvorba tipa).<br />

Statičko (ili leksičko ) povezivanje se vrši prije izvršenja programa— za vrijeme kompiliranja<br />

Primjer (C jezik):<br />

int x,z;<br />

void A() {<br />

float x,y;<br />

print(x,y,z); // use global var z<br />

}<br />

void B(int y) {<br />

print (x,y,z) // use global vars x,z<br />

}<br />

21


Blok struktura<br />

U većini slučajeva blok struktura znači:<br />

Nije moguć pristup identifikatorima izvan njihova dosega.<br />

Primjenjuje se najbliţa prethodna deklaracija.<br />

Lokalne varijable se automatski alociraju i dealociraju<br />

Postoje varijacije od ovih pravila. U Javi se moţe koristiti objekt tek kada je kreiran pomoću new operatora,<br />

Primjerice,<br />

...<br />

Object Obj;<br />

...<br />

stvara referencu Java objekta ali ne i memoriju za taj objekt.<br />

Tek kada se izvrši stvaranje objekta s<br />

Object Obj = new Object();<br />

...<br />

njemu se moţe pristupiti.<br />

22


Dinamički doseg<br />

Pod dinamičkim dosegom podrazumijeva se da se za identifikator uzima deklaracija koja je najbliţe prema vremenu<br />

izvršenja programa. Taj se princip koristio u ranim verzijama jezika Lisp.<br />

Problem nastaje ako varijabla nije lokalno deklarirana. Primjerice, problem je ilustriran s kvazi-C jezikom<br />

int x;<br />

void print()<br />

{<br />

write(x);<br />

}<br />

main () {<br />

bool x;<br />

print();<br />

}<br />

Kod statičkog povezivanja x se ispisuje u funkciji print() kao tip int, jer je int x, globalno deklariran.<br />

Kod dinamičkog povezivanja, pošto print nema lokalnu deklaraciju za x, ispituje se pozvana funkcija u kojoj je x tipa<br />

bool.<br />

Dinamičko povezivanje je vrlo teško provesti, stoga se ono izbjegava. Ono čak izgleda i bizarno, ali se ipak koristi, i to kod<br />

virtualnih funkcija u C++, C# i Java jeziku.<br />

23


Virtualne funkcije<br />

Primjer: C# jezik – dinamičko povezivanje s virtualnim funkcijama<br />

using System;<br />

class C {<br />

public void DoIt() {PrintIt();}<br />

public virtual void PrintIt() {Console.WriteLine("C rules!");}<br />

}<br />

class D : C {<br />

override public void PrintIt() {Console.WriteLine("D rules!");}<br />

public void TestIt() {DoIt();}<br />

}<br />

class Test{<br />

public static void Main() {<br />

D dvar = new D();<br />

dvar.TestIt();<br />

}<br />

}<br />

//D rules! is printed.<br />

24


U jeziku Java – "sve metode su virtualne"<br />

Primjer:<br />

class C {<br />

void DoIt() {PrintIt();}<br />

void PrintIt() {System.out.println("C rules!");}<br />

}<br />

class D extends C {<br />

void PrintIt() {System.out.println("D rules!");}<br />

void TestIt() {DoIt();}<br />

}<br />

class Test {<br />

public static void main (String args[]) {<br />

D dvar = new D();<br />

dvar.TestIt();<br />

}<br />

}<br />

//D rules! is printed.<br />

25


Domaći rad: Napišite C++ program koji daje isti izlaz.<br />

26


Doseg i životnost<br />

Obično se zahtijeva da ţivotnost varijable bude barem jednaka vremenu koji odgovara izvršenu dosega varijable.<br />

Ţivotnost nekih objekata nadmašuje njihov doseg. Primjer za to su static ili own varijable.<br />

void f() {<br />

static int i = 0;<br />

print(i++);<br />

}<br />

Svaki poziv f() ispisuje različitu vrijednost od i (0, 1, ...) . Varijabla i zadrţava vrijednost izmeĎu poziva funkcije.<br />

Neki <strong>jezici</strong> dozvoljavaju inicijaliziranje varijabli u svakom dosegu.<br />

ML<br />

Let<br />

id = val<br />

in<br />

statements<br />

end;<br />

C<br />

{<br />

type id = val;<br />

statements<br />

}<br />

27


Strukture i blokovi<br />

Podaci se grupiraju u strukture:<br />

struct complex { float re, im; }<br />

a programski kod se grupira u blokove:<br />

{<br />

}<br />

float re, im;<br />

re = 0.0; im = 1.0;<br />

Iako slično izgledaju, blok i struktura su potpuno različiti entiteti:<br />

o Strukture su podaci,<br />

o Blokovi sadrţe programski kod i deklaracije,<br />

Ako u strukturu dodamo definiciju funkcija i inicijalizacijski kod (konstruktora i destruktora) dobije se definicija klase:<br />

class complex<br />

{<br />

public:<br />

float re, im;<br />

complex (float v1, float v2){ re = v1; im = v2; }<br />

}<br />

28


Klase<br />

Klasa se koristi za stvaranje jednog ili više objekata<br />

Deklarirane varijable se nazivaju članovi ili polja, a deklarirane funkcije se nazivaju metode ili članske funkcije klase,<br />

Dvije posebne funkcije, kojima se ne zadaje tip, i koje imaju ime klase , predstavljaju konstruktor i destruktor klase<br />

Unutar klase članovi se mogu grupirati s atributom public, private ili protected, što označava razinu dozvole pristupa<br />

članovima klase.<br />

Ekvivalentnost tipa za klase<br />

Klase dijelo moţemo tretirati i kao tipove podataka.<br />

U C++ i Javi, objekti neke klase su ekvivalentnog tipa i mogu se pridjeljivati jedan drugom, pr.<br />

class MyClass {<br />

...<br />

}<br />

MyClass v1, v2;<br />

v1 = v2; // Pridjela vrijednosti je OK<br />

Ova naredba pridjele vrijednosti ne mora biti uvijek u C++ izvršena s ţeljenim učinkom.<br />

Pogledajmo slučaj u Javi i C++<br />

29


JAVA<br />

Razmotrimo klasu Point kojom se može stvarati n-dimenzionalne točke:<br />

class Point { // in Java<br />

int dimensions;<br />

float coordinates[];<br />

Point () {<br />

dimensions = 2;<br />

coordinates = new float[2];<br />

}<br />

Point (int d) {<br />

dimensions = d;<br />

coordinates = new float[d];<br />

}<br />

}<br />

Point plane = new Point();<br />

Point solid = new Point(3);<br />

plane = solid; //OK u Javi<br />

U Javi je dozvoljeno pridjeljivanje objekata iste klase, iako u ovom primjeru, od dvodimenzionalne točke stvaramo<br />

trodimenzionalnu točku.<br />

30


U C++ postoji problem plitkog i dubokog kopiranja, koji se rješava tako da korisnik sam definira operator pridjele<br />

vrijednosti. Ortodoksni kanonički oblik klase u C++ zahtijeva da se definira a) konstruktor, b) destruktor, c) operator = i d)<br />

kopirni konstruktor:<br />

#include <br />

class Point {<br />

public:<br />

int dimensions;<br />

float *coordinates;<br />

Point (int d = 2) {<br />

dimensions = d;<br />

coordinates = new float[d];<br />

}<br />

~Point() {delete [] coordinates;}<br />

// mora se definirati za dinamički<br />

// alocirane članove<br />

Point &operator =(Point &p) {<br />

if(this == &p) return *this;<br />

if(p.dimensions != dimensions) {<br />

delete [] coordinates;<br />

coordinates = new float[p.dimensions];<br />

}<br />

for(int i=0; icoordinates[i]=i;<br />

plane = solid; //OK in if operator = defined<br />

// but plane is now 3d point<br />

for (i=0; idimensions; i++)<br />

std::cout coordinates[i]


Subklase nisu ekvivalentnog tipa<br />

Temeljna se klasa naziva superklasa, a izvedene klase se nazivaju subklase. TakoĎer se za temeljnu klasu koristi<br />

naziv roditelj (parent class), a izvedene klase se nazivaju djeca (child classes),<br />

U C++, C# i Javi subklase (ili subtipovi) se stvaraju pomoću nasljeĎivanja, ali to ne znači da se te klase istog tipa<br />

Primjer u Javi:<br />

class Point2 extends Point<br />

{<br />

Point2() {super(2); }<br />

}<br />

// super je konstruktor roditelja<br />

class Point3 extends Point<br />

{<br />

Point3() {super(3); }<br />

}<br />

Point2 plane = new Point2();<br />

Point3 solid = new Point3();<br />

plane = solid; //Illegal in Java<br />

32


C++:<br />

class Point2 :public Point {<br />

public:<br />

Point2() : Point(2) {}<br />

};<br />

class Point3 :public Point {<br />

public:<br />

Point3() : Point(3) {}<br />

};<br />

int main()<br />

{<br />

Point2 *plane = new Point2();<br />

Point3 *solid = new Point3();<br />

for (i=0; idimensions; i++)<br />

solid->coordinates[i]=i;<br />

plane =reinterpret_cast (solid);<br />

//OK if type cast<br />

for (int i=0; idimensions; i++)<br />

std::cout coordinates[i]


Izlaz je: 0 1 2<br />

Ako se deklarira u C++:<br />

class Point2 :public Point {<br />

public:<br />

Point2() { Point(2); } // umjesto Point2() : Point(2) {}<br />

};<br />

class Point3 :public Point {<br />

public:<br />

Point3() { Point(3); } // umjesto Point3() : Point(3) {}<br />

};<br />

Za main() isti kao prije<br />

izlaz je: 0 1<br />

Objasni: Zašto je nestala treća dimenzija?<br />

Problem je u korištenju konstruktora :<br />

Point3() { Point(3); } umjesto Point3() : Point(3) {}<br />

Zaključak: Dobro je da nas Java čuva od ovakovih grešaka.<br />

34


Generičke klase i parametrički polimorfizam<br />

Postavlja se pitanje, kako se moţe stvarati napredne strukture podataka koje se mogu primijeniti na različite tipove.<br />

Primjerice, moţe li se napraviti klasu za vezanu listu koja će moći sadrţavati različite tipove podataka.<br />

Najjednostavniji način je primijenjen u jeziku Java, na način da sve klase nasljeĎuju jedinstvenu temeljnu klasu Object.<br />

U Javi se onda vezana lista definira sljedećom klasom:<br />

class LinkedList<br />

{<br />

Object value;<br />

LinkedList next;<br />

Object head() {return value;}<br />

LinkedList tail(){return next;}<br />

LinkedList(Object O)<br />

{value = O; next = null;}<br />

LinkedList(Object O,LinkedList L)<br />

{value = O; next = L;}<br />

}<br />

Vidimo da ova klasa sadrţi objekte tipa Object. Pošto je referenca objekta u Javi zapravo pokazivač objekta tada se ovom<br />

objektu moţe pridijeliti objekt bilo kojeg tipa, ali:<br />

o Mora se vršiti pretvorba tipa Object u stvarni tip ako ţelimo dobiti objekt iz liste<br />

o Za pretvorbu tipa mora postojati definirana klasa. Primjerice ako ţelimo da lista sadrţi cijele brojeve za<br />

pretvorbu tipa nam je potrebna klasa Integer a ne primitivni tip int (jer primitivni tip nije klasa).<br />

35


Primjer, manipuliranje s vezanom listom koja sadrţi cijele brojeve :<br />

LinkedList l =new LinkedList(new Integer(123));<br />

int i = ((Integer) l.head()).intValue();<br />

Očito je ovaj pristup u Javi, a slično je bilo i u prvim bibliotekama C++, dosta nepraktičan. Zbog toga je u C++ uveden<br />

mehanizam predložaka (template) a sada se uvodi u C# i u Javu (probna verzija je dana u jeziku Pizza). Mahanizam<br />

predloţaka stvara generičke klase i to se naziva parametrički polimorfizam.<br />

Evo kako izgleda generički definirana vezana lista u jeziku Pizza:<br />

class LinkedList {<br />

T value;<br />

LinkedList next;<br />

T head() {return value;}<br />

LinkedList tail() {return next;}<br />

LinkedList(T O) {value = O; next = null;}<br />

LinkedList(T O,LinkedList L){value=O; next=L;}<br />

}<br />

LinkedList l = new LinkedList(123);<br />

int i = l.head();<br />

Isto kao u C++ parametrički tip se zapisuje u zagradama , a stvarni tip se definira pri deklaraciji objekta.<br />

36


Preopterećenje (Overloading) funkcija ili ad-hoc polimorfizam<br />

U klasama se često definira više funkcija (ili konstruktora) s istim imenom ali s različitim parametrima. To zovemo<br />

preopterećenjem funkcije. Primjer:<br />

class MyClass {<br />

int f(int i) { ... }<br />

int f(float g) { ... }<br />

int f(int i, int j) { ... }<br />

}<br />

C++ i Java ne dozvoljavaju de se preopterećene funkcije razlikuju po povratnoj vrijednosti, već moraju biti različiti<br />

parametri funkcije (broj parametara ili tip) To znači da<br />

class MyClass {<br />

int f() { ... }<br />

float f() { ... }<br />

}<br />

nije dozvoljeno.<br />

37


Preopterećenje operatora<br />

C++ i C#, dozvoljavaju preopterećenje (promjenu značenja) postojećih operatora. Primjer:<br />

class MyClass {<br />

int i;<br />

public:<br />

int operator+(int j) { return i+j; }<br />

}<br />

MyClass c;<br />

int i = c+10;<br />

int j = c.operator+(10);<br />

int k = 10+c; // Nije dozvoljeno!<br />

Izraz 10+c nije ispravan jer nije definirano djelovanje operatora + za objekte tipa int i MyClass&. To se moţe<br />

ostvariti u C++ pomoću friend mehanizma, koji omogućuje pristup private članovima:<br />

class MyClass {<br />

int i;<br />

public:<br />

int operator+(int j) {return i+j; }<br />

friend int operator+ (int j, MyClass& v) {return j+v.i; }<br />

}<br />

MyClass c;<br />

int k = 10+c; // OK!<br />

C++ dozvoljava preopterećenje postojećih operatora. Neki <strong>jezici</strong>, poput Algola 68 dozvoljavaju definiranje novih operatora.<br />

38


Prijenos argumenata (stvarnih parametara) funkcije<br />

Stvarni parametar ili argument funkcije je objekt koji se deklarira kao formalni parametar funkcije. On ima ime, i<br />

vrijednost i adresu (ukoliko nije konstanta). U funkciju se mogu prenositi sve tri značajke argumenta. Koriste se sljedeći<br />

nazivi za prijenos argumenata u funkciju:<br />

Prenosi se<br />

Vrijednost: Formalni parametar se tretira kao lokalna varijabla koja se inicijalizira na vrijednost argumenta. To je<br />

standardni oblik prijenosa vrijednosti konstanti i skalarnih varijabli u C i Javi.<br />

Referenca: Formalni parametre je pokazivač na stvarni parametar. Koristi se u C++ i C za prijenos nizova i varijabli.<br />

Rezultat: Formalni parametar se tretira kao lokalna varijabla. Njena konačna vrijednost se nakon završetka funkcije<br />

kopira u stvarni argument funkcije.<br />

Vrijednost/Rezultat: Kombinacija dva moda. Formalni parametar se tretira kao lokalna varijabla koja se inicijalizira<br />

na vrijednost argumenta. Nakon završetka funkcije rezultat se upisuje u stvarni argument.<br />

Ime: Formalni parametar predstavlja blok koda (zovemo ga thunk) koji se evaluira da bi se dobila vrijednost ili<br />

adresa argumenta. Koristi se jedino u jeziku Algol.<br />

Read-only (Const): Dozvoljen je argument koristiti samo kao konstantu.<br />

Koji se načini prijenosa argumenata stvarno koristi?<br />

• C jezik koristi se prijenos vrijednosti, jedino se nizovima prenosi referenca (adresa nultog elementa)<br />

• C++ dozvoljava prijenos reference varijable<br />

void swap(int &a, int &b) {int t = a; a = b; b = t:}<br />

39


• C#: koristi prijenos vrijednosti, reference i rezultata;<br />

int g(int a, out int b)<br />

• Java: Skalarni tipovi (int, float, char, etc.) se prenose po vrijednosti, a objekti po referenci.<br />

• Fortran: prenosi se referenca (čak i za konstante).<br />

• Ada prenosi vrijednost / rezultat, reference i readonly konstante.<br />

Zašto se koriste različiti modovi prijenosa argumenata funkcije?<br />

o Prijenos vrijednosti štiti aktualni parametar - on se ne mijenja već se mijenja formalni parametar, koji je lokalna<br />

varijabla.<br />

o Prijenos readonly je ekvivalentan prijenosu vrijednosti, ali se naglašava ―konstantni‖ karakter argumenta.<br />

o Prijenos reference omogućuje mijenjanje argumenta. To moţe stvoriti bočne efekte, pa se koristi samo u iznimnim<br />

slučajevima.<br />

o Prijenos vrijednosti/rezultata ima efekt kao prijenos reference, ali se to izvršava na drugi način. Umjesto neposredne<br />

promjene argumenta, on se mijenja tek po završetku funkcije..<br />

o Prijenos imena odlaţe promjenu aktualnog parametra dok on stvarno ne bude korišten u nekom izrazu ( moţda i<br />

nikada. Da bi shvatili tu vrstu prijenosa razmotrimo poziv f(i,j/0). Kod normalnog poziva prvo se evaluira<br />

j/0, što daje divide fault i program završava. Ako se j/0 prenosi po imenu tada se dijeljenje odlaţe dok ne<br />

bude potreban drugi argument, a to moţe biti nikada.<br />

Prijenos po imenu je sličan onome što se kod funkcionalnih jezika naziva "lazy evaluation" (odloženo evaluiranje<br />

argumanta). Kod "lazy evaluation", ne vrši se proračun vrijednosti argumenta već se definira posebna funkcija<br />

suspension— koja daje vrijednost kada ona bude potrebna. Suprotno od "lazy evaluation" je "eagger evaluation" gdje se<br />

argumenti evaluiraju čim su definirani.<br />

40


Ekvivalentnost tipova<br />

Provjera tipova se obično radi za vrijeme kompiliranja – to zovemo static typing.<br />

Provjera tipova se moţe raditi i za vrijeme izvršenja programa - to zovemo dynamic typing.<br />

Program je tipski-siguran (type-safe) ako nije moguće primijeniti operacije na nekompatibilne tipove podataka.<br />

Čvrsto tipizirani (Strongly-typed) programski jezik zabranjuje formiranje (ili izvršenje) tipski-nesigurnih programa.<br />

Slabo tipizirani (Weakly-typed) programski jezik omogućije formiranje (ili izvršenje) tipski-nesigurnih programa.<br />

Java je čvrsto tipizirani jezik, a C i C++ su slabo tipizirani <strong>jezici</strong> koji dozvoljavaju da se zaobiĎu tipska pravila, primjerice:<br />

int i;<br />

int* p;<br />

p = (int *)i * i;<br />

Sada se p moţe koristiti kao pokazivač na int premda mnoţenje moţe rezultirati nedozvoljenim pokazivačem.<br />

Kod kontrole tipova prvo se utvrĎuje da li su dva objekta, iz nekog izraza, koji imaju tipove T1 i T2, tipski ekvivalentan.<br />

Koristi se dvije definicije tipske ekvivalentnosti:<br />

o ekvivalencija po imenu<br />

o strukturalna ekvivalencija.<br />

41


Ekvivalencija po imenu<br />

Dva tipa su ekvivalentna ako označavaju istu vrst deklaracije.<br />

Primjer:<br />

typedef int i;<br />

int j;<br />

Očito su tipovi od x i y ekvivalentni.<br />

Primjer,<br />

type PackerSalaries = int[100];<br />

type AssemblySizes = int[100];<br />

PackerSalaries salary;<br />

AssemblySizes size;<br />

Sada salary = size; nema ekvivalenciju po imenu<br />

Formalno, definira se N (ekvivalencija po imenu) s:<br />

(a) T N T<br />

(b) Za deklaraciju oblika<br />

Type T1 = T2;<br />

T1 N T2<br />

U analizi se anonimni tipovi tretiraju kao da imaju jedinstveno ime, tako<br />

int A[10]; se razmatra kao typedef int[10] T;<br />

T A;<br />

42


Strukturalna ekvivalencija<br />

Dva tipa su strukturalno ekvivalentna ako imaju istu definiciju članova strukture . Strukturalna ekvivalencija se označava s<br />

S, a definira se na sljedeći način:<br />

(a) T S T<br />

(b) Za deklaraciju oblika<br />

Type T = Q;<br />

T S Q<br />

ako T i Q su definirani pomoću istih konstruktora tipa i na isti način.<br />

To znači da u prijašnjem primjeru<br />

type PackerSalaries = int[100];<br />

type AssemblySizes = int[100];<br />

PackerSalaries salary;<br />

AssemblySizes size;<br />

salary S size<br />

pošto su oba niza s 100=100 i int S int.<br />

C i C++ u kontroli tipova koriste strukturalnu ekvivalenciju osim za strukture i klase, kod kojih se koristi ekvivalencija po<br />

imenu. Kod nizova ignorira se veličina niza. Java koristi strukturalnu ekvivalenciju za skalarne tipove. Kod nizova<br />

zahtijeva ekvivalenciju po imenu, bez obzira na veličinu niza. Za klase koristi ekvivalenciju po imenu osim što se moţe<br />

koristiti podklasa na mjestu gdje je definirana klasa.<br />

43


To znači da za definiranu funkciju:<br />

void fun(Object O) { ... };<br />

poziv<br />

fun(new Integer(100));<br />

je ispravan jer je Integer subklasa od Object.<br />

Automatska pretvorba tipova<br />

C, C++ i Java dozvoljavaju pretvorbu tipova, od toga neke pretvorbe se vrše automatski<br />

In C, C++ i Java, float se automatski stvara od tipa int, u izrazu:<br />

float f = 10; // No type error<br />

Cjelobrojni tipovi (char, short, int, long) sa automatski "proširuju":<br />

int i = 'x'; // OK - char u int<br />

U C i C++ (ali ne u Javi), cijeli broj se moţe i "suziti" s mogućim gubitkom bitova:<br />

char c = 1000000; //dozvoljeno u C++ ali ne u Javi<br />

44

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!