270 likes | 472 Views
Operatori. Operatori kreiraj u izraze od pojedinačnih podataka – kombinuju vrednosti u izraze Semantika operatora – značenje (funkcija operatora), zavisi ne samo od operatora, već i od podataka
E N D
Operatori • Operatorikreirajuizraze od pojedinačnih podataka – kombinuju vrednosti u izraze • Semantika operatora – značenje (funkcija operatora), zavisi ne samo od operatora, već i od podataka • Na pr. operator + sabira brojeve i konkatenira stringove, što su različite, ali sasvim slične operacije • Prioritet operatora – precedence definiše podrazumevani redosled primene dva ili više različitih operatora kada se ne koriste zagrade koje eksplicitno definišu redosled primene različitih operatora • a + b * c = a + (b * c) • Asocijativnost operatora definiše redosled primene dva ili više puta ponovljenog istog operatora • a = b = c je isto što i a = (b = c).
Operatori • Unarni operatori imaju jedan operand (++, --) • Binarni operatori dva... (+, *, /, ....) • Ternarni – conditional operator (a>b)?max=a:max=b • Compound – složeni operatori (+=, *=, &=, ...)
Preklapanje operatora • Operatori se mogu preklapati tako da se mogu prilagođavati korisnički definisanim tipovima • Pri tome postoje neka ograničenja koja određuju kako se operatori mogu preklapati • Prioritet i asocijativnost operatora se ne mogu menjati i ne zavise od tipa podataka • Ne može se menjati multiplicitet operatora – broj operanada (unarni, binarni, ternarni) • Ne mogu se uvoditi / kreirati novi tipovi operatora • Ako je ipak potrebno da se kreira novi tip operatora, onda se može napisati metod umesto operatora
Preklapanje operatora • Ne može se menjati smisao operatora kada deluju na ugrađene tipove podataka • Postoje operatori koji ne mogu da se preklapaju, na pr “.” – tačka operator • Navedena ograničenja postoje da bi se stvari pojednostavile sa jedne strane i da bi se sprečilo nepotrebno komplikovanje koda • Slično tome se na pr mogu shvatiti neka ograničenja u C#-u u odnosu na C++, višestruko nasleđivanje, eksplicitno postavljanje vrednosti pokazivača – adrese, eksplicitno brisanje objekata – oslobađanje memorije, mogućnost kreiranja objekata na stack-u, itd.
Preklapanje operatora • Mogu se preklapati samo postojeći operatori koji deluju na korisničke tipove • Sintaksa za preklapanje operatora je sasvim slična kao kod metoda, sa tim što je naziv metoda operator<operator symbol> • Primer je korisnička struktura Hour sa jednim podatkom članom tipa int • Definiše se preklopljeni operator + za sabiranje podataka tipa Hour • Šta uopšte znači sabrati dva podatka tipa Hour? • Upravo to se definiše preklapanjem operatora +
struct Hour { public Hour(int initialValue) { this.value = initialValue; } public static Hour operator+ (Hour lhs, Hour rhs) { return new Hour(lhs.value + rhs.value); } ... private int value; }
Pseudo kod za + operator Hour Example(Hour a, Hour b) { return a + b; } Hour Example(Hour a, Hour b) { return Hour.operator+(a,b); // pseudocode }
Mešoviti argumenti preklopljenog operatora • Argumenti preklopljenog operatora mogu biti različiti • Neophodno je da jedan od argumenata mora biti korisničkog tipa • Na taj način se olakšava compiler-u da prepozna preklopljeni operator, kao i da se onemogući promena funkcije operatora na ugrađene tipove – jer nije moguće preklopiti operator koji deluje na ugrađene tipove – jedan od tipova operanada mora biti korisničkog tipa • Drugi operand može biti ugrađenog tipa
Simetrični operatori • Hour a = ...; • int b = ...; • Hour sum = a + new Hour(b); • Moguće je kreirati preklopljeni operator sa operandima različitog tipa • Hour a = ...; • int b = ...; • Hour sum = a + b; • Neophodno je definisati dodatnu preklopljenu verziju operatora + za sabiranje tipa Hour i int
struct Hour { public Hour(int initialValue) { this.value = initialValue; } ... public static Hour operator+ (Hour lhs, Hour rhs) { return new Hour(lhs.value + rhs.value); } public static Hour operator+ (Hour lhs, int rhs) { return lhs + new Hour(rhs); } ... private int value; } Preklopljeni oeprator za sabiranje različitih tipova - Hour i int koristi prethodni kod i omogućava enkapsulaciju tog koda kao i lakše i elegantnije sabiranje različitih tipova podataka
Simetričan slučaj • int a = ...; • Hour b = ...; • Hour sum = a + b; // compile-time error • Neophodno je posebno definisati preklopljeni operator + za sabiranje simetričnog slučaja • public static Hour operator+ (int lhs, Hour rhs) • { • return new Hour(lhs) + rhs; • }
Visual basic i ostali... • Ako se kreiraju klase u C#-u koje treba da se koriste iz drugih .NET jezika, koji ne podržavaju preklapanje operatora, kao na pr. Visual basic, onda je neophodno obezbediti dodatni metod (Add) koji će igrati ulogu preklopljenog operatora, tj. pružati istu funkcionalnost kao i preklopljeni operator • public static Hour Add(Hour lhs, int rhs) • { • ... • }
Compound – složeni operatori • Pri korišćenju složenih – compound operatora može doći do raznih interesantnih posledica vezanih za preklapanje operatora • Izraz a @= bznači a = a @ b • Hour a = ...; • int b = ...; • a += a; // same as a = a + a • a += b; // same as a = a + b • Ali, sa b +=aje problem zbog b = b + a • Sabiranje b+a može da se izvrši jer je definisan odgovarajući preklopljeni operator, ali dodela ne može da se izvrši jer treba int-u dodeliti Hour što nije moguće pošto se operator = NE MOŽE PREKLOPITI!!!
++ i -- operatori struct Hour { ... public static Hour operator++ (Hour arg) { arg.value++; return arg; } ... private int value; }
Prefix i postfix forme ++ i -- • Hour now = new Hour(9); • Hour postfix = now++; • Postfix forma se prevodi u: • Hour now = new Hour(9); • Hour postfix = now; • now = Hour.operator++(now); // pseudocode, not valid C# • Hour now = new Hour(9); • Hour prefix = ++now; • Prefix forma se prevodi u: • Hour now = new Hour(9); • now = Hour.operator++(now); // pseudocode, not valid C# • Hour prefix = now;
Postfix sa klasom • Kod sa prethodne strane za Postfix ne radi sa klasom • Razlog je da je klasa referenti tip i da dodela u stvari znači dodela adrese, tako da promenljiva postfix tipa Hour posle dodele u stvari sadrži adresu na objekat,pa kada se podatak član objekta uveća za jedan, to se vidi i u postfix, a ne bi trebalo. • Ispravna implementacija increment operatora za klasu bi bila: • public static Hour operator++(Hour arg) • { • return new Hour(arg.value + 1); • }
Parovi operatora • Neki operatori su logički povezani u smislu da jedan operator predstavlja logičku negaciju drugog • Primeri za takve operatore su: • == i != • < i > • <= i >= • Ako se jedanodtihoperatorapreklopi, obavezno je da se preklopii operator sakojim je uparen – negacija, što je ilogično, jer jedan može da zameni drugi kada se negira • C# compiler ne kreira automatski onaj drugi operator, već je to potrebno posebno uraditi
struct Hour { public Hour(int initialValue) { this.value = initialValue; } ... public static bool operator==(Hour lhs, Hour rhs) { return lhs.value == rhs.value; } public static bool operator!=(Hour lhs, Hour rhs) { return lhs.value != rhs.value; } ... private int value; } Izlazni tip ne mora da bude bool, ali kakvog bi smisla imalo vraćati nesto drugo?
Konverzija tipova podataka • Konverzija podataka iz jednog tipa u drugi tip može biti dvojaka – implicitna i eksplicitna • Kod ugrađenih tipova podataka, implicitna konverzija se vrši kod tzv. widening (širenje) konverzija gde se jedan tip konvertuje u tip koji ima veću tačnost – širi tip • Primer za to je kada se int konvertuje u double, pri čemu se ništa ne gubi i konverzija ne treba da se eksplicitno naglašava, već compiler u takvom slučaju to neprimetno odradi jer se radi o sigurnoj konverziji • Example.MyDoubleMethod(42); // implicit int-to-double conversion
Konverzija tipova podataka • Ako je potrebno širi tip – veće tačnosti konvertovati u uži tip – manje tačnosti, onda je neophodno primeniti eksplicitnu konverziju koja se mora navesti u kodu – type cast. • Ako se eksplictno ne navede type cast u slučaju “sužavanja” – “narrowing conversion”, prijavljuje se greška • Example.MyIntMethod(42.0); // compile-time error • Example.MyIntMethod((int)42.0); • Može se definisati konverzija korisničkih tipova podataka - implicitna i eksplicitna, slično preklapanju operatora
Konverzija korisničkih tipova struct Hour { ... public static implicit operator int (Hour from) { return from.value; } private int value; } Gornji kod definiše implicitnu konverziju iz tipa Hour u tip int koji se i vraća
Konverzija korisničkih tipova Kada se koristi implicitna konverzija, onda se ne zahteva type cast, već compiler automatski odrađuje definisanu konverziju korisničkih tipova class Example { public static void MyOtherMethod(int parameter) { ... } public static void Main() { Hour lunch = new Hour(12); Example.MyOtherMethod(lunch); // implicit Hour to int conversion } }
Konverzija korisničkih tipova • Ako se konverzija korisničkih tipova deklariše kao eksplicitna, prethodni primer se neće kompajlirati, jer je neophodno navesti type cast • Example.MyOtherMethod((int)lunch); // explicit Hour to int conversion • Konverzija se može deklarisati kao implicitna u slučaju kada ne dolazi do gubitka informacija, kada je konverzija sigurna i kada ne može doći do generisanja izuzetaka pri konverziji • U suprotnom, se konverzija deklariše kao eksplicitna i onda je u kodu neophodno navesti odgovarajući type cast
Simetrični operatori • Ako su potrebne različite verzije preklopljenog operatora + kao na pr: • Hour + Hour • Hour + int • int + Hour • Onda se takav problem može rešiti na dva načina: • 1) Kreiranjem 3 različita preklopljena operatora za svaki od navedenih slučajeva • 2) kreiranjem jednog + operatora za Hour + Houri jednog implicitnog konverzionog operatora Hour u int
struct Hour { public Hour(int initialValue) { this.value = initialValue; } public static Hour operator+(Hour lhs, Hour rhs) { return new Hour(lhs.value + rhs.value); } public static implicit operator Hour (int from) { return new Hour (from); } ... private int value; } Sabiranje Hour i int funkcioniše u obe kombinacije: Hour + int kao i int + Hour void Example(Hour a, int b) { Hour eg1 = a + b; // b converted to an Hour Hour eg2 = b + a; // b converted to an Hour }