03-PreklapanjeOperatora

Download Report

Transcript 03-PreklapanjeOperatora

Preklapanje operatora

     Tipovi operatora Tipovi podataka i efekat operatora Pojam preklapanja operatora Operatorske funkcije Konverzije tipova

 Korišćenjem operatora Matrix a, b, c; Matrix d = c * (a + b);  Bez operatora, korišćenjem metoda Matrix a, b, c; Matrix d = c.Multiply(a.Add(b));

  ◦ ◦ Dvije kategorije tipova Value types    Prosti tipovi (int, byte, float...) i strukture Direktno sadrže vrijednost Vrijednost se čuva u stack dijelu memorije Reference types    Klasni tipovi Sadrže referencu na vrijednost (adresu memorijske lokacije) Vrijednost se čuva u managed heap dijelu memorije Zavisno od kategorije tipa, razlikuje se način izvršavanja operacija nad podacima tog tipa

Type

Value Type Reference Type

Value Types Built-in Type  int  float User-Defined  enum  struct

// i, j su tipa int i = 20; j = i; i++; j+=2; Console.WriteLine(i); Console.WriteLine(j);  Koje vrijednosti se ispisuju?

 Kreiranje varijabli coordinate c1; c1 = new coordinate(); c1.x = 6.12; c1.y = 4.2;  Uklanjanje reference c1 = null; • • 6.12 4.2

6.12 4.2

c1 c2 • • 2.3 7.6

coordinate c1= new coordinate( ); coordinate c2; c1.x = 2.3; c1.y = 7.6; c2 = c1; Console.WriteLine(c1.x + " , " + c1.y); Console.WriteLine(c2.x + " , " + c2.y);

  ◦ Poređenje Value tipova Operatori “==“ i “!=“ porede vrijednosti ◦ Poređenje Reference tipova Operatori “==“ i “!=“ porede reference, ne porede vrijednosti • 1.0 2.0

Dvije različite reference na iste vrijednosti • 1.0 2.0

//Vektor je klasa koja posjeduje javni atribut Vrijednost Vektor x, y; x = new Vektor(); x.Vrijednost = 30; y = x; Console.WriteLine(y.Vrijednost); y. Vrijednost = 50; Console.WriteLine(x. Vrijednost);  Koje vrijednosti se ispisuju?

   Način poređenja zavisi od tipa objekta, odnosno da li je Value ili Reference tipa Kod varijabli koje su Value tipa (prosti tipovi, instance struktura ili nabrojanja) porede se vrijednosti Kod varijabli koje su Reference tipa (klasni tipovi, instance klasa) porede se reference, odnosno adrese memorijskih lokacija

 ◦ ◦ ◦ System.Object, nekoliko metoda poređenja ReferenceEquals()     Ispituje da li su dvije reference iste, tj da li pokazuju na istu instancu objekta u memoriji Nema smisla da se koristi za Value tipove Equals()   Poredi reference za Reference tipove, može se predefinisati za korisničke klase Poredi vrijednosti za Value tipove Operator poređenja (==) Za Reference tipove poredi reference, može se predefinisati Za Value tipove poredi vrijednosti, potrebno ga je redefinisati za korisničke tipove (strukture)

 ◦ ◦ Preklapanje operatora (operator overloading) predstavlja redefinisanje postojećih operatora zbog potrebe da na specifičan način rade sa novim tipovima podataka (npr. klasnim tipovima) omogućava da se ugrađeni operatori prilagode tako da izvršavaju određenu akciju nad objektima klasnih tipova

   Moguće je izvršiti preklapanje skoro svih operatora Preklapanje operatora treba pažljivo koristiti, zbog mogućih neželjenih efekata Primjeri korištenja preklapanja operatora kod ugrađenih tipova ◦ operator dodjele se koristi na isti način za različite tipove podataka ◦ operator sabiranja se koristi i za cijele i za realne brojeve

   Za korištenje operatora nad objektima klasnih tipova u opštem slučaju potrebno je preklapanje operatora Preklapanje se vrši tako što se definiše operatorska funkcija Operatorske funkcije se implementiraju: ◦ kao metode ◦ kao globalne funkcije, obično prijateljske funkcije klasa (C++)

      Pretpostavimo da su u programu potrebni kompleksni brojevi i operacije nad njima. Tip kompleksnog broja će realizovati klasa koja sadrži elemente (real, imag), a takođe i funkcije za operacije.

Pogodno je da se pozivi funkcija koje realizuju operacije mogu notacijski predstaviti standardnim operatorima.

U jezicima C#/C++, operatori za korisničke tipove (klase) su specijalne operatorske funkcije.

Operatorske funkcije nose ime operator@, gde je @ neki operator ugrađen u jezik.

Operatorske funkcije preklapaju standaradne operatore (+, -, *, /, ...).

  Operatorske funkcije se mogu koristiti u izrazima kao i operatori nad ugrađenim tipovima. Ako je operatorska funkcija definisana na prethodno opisan način, izraz t1@t2 se tumači kao operator@(t1,t2):

class

complex {

public

: complex(

double

,

double

); /* konstruktor */

friend

complex

operator

+(complex,complex); /* oparator + */

friend

complex

operator

-(complex,complex); /* operator - */

private

:

double

real, imag; }; complex::complex (

double

r,

double

i) : real(r), imag(i) {} complex

operator

+ (complex c1, complex c2) { complex temp(0,0); // privremena promenljiva tipa complex temp.real=c1.real+c2.real; temp.imag=c1.imag+c2.imag;

return

temp; } complex

operator

- (complex c1, complex c2) {

return

complex(c1.real-c2.real,c1.imag-c2.imag); //poziv konstruktora }

} { struct Vector { public double x, y, z; public Vector(Vector rhs) x = rhs.x; y = rhs.y; z = rhs.z; { } public static Vector operator + (Vector lhs, Vector rhs) Vector result = new Vector(lhs); result.x += rhs.x; result.y += rhs.y; result.z += rhs.z; return result; }

  C#/C++ dozvoljava preklapanje operatora kao što dozvoljava i preklapanje imena funkcija.

Princip preklapanja omogućava da se definišu nova značenja operatora za korisničke tipove.

 Postoje neka ograničenja u preklapanju operatora: ◦ ne mogu direktno da se preklope svi operatori, neki ne mogu nikako; ◦ ◦ ◦ ne mogu da se redefinišu značenja operatora za primitivne (standardne) tipove podataka; ne mogu da se uvode novi simboli za operatore; ne mogu da se mijenjaju osobine operatora koje su ugrađene u jezik: asocijativnost.

n -arnost, prioritet i

  Ako je @ neki binarni operator (npr +), on može da se realizuje: ◦ ◦ Kao funkcija članica klase X Kao prijateljska globalna funkcija Nije dozvoljeno da se u programu nalaze obje ove funkcije

operator@ (X) Poziv a@b se sada tumači kao: a.operator@(b) , za funkciju članicu

operator@ (X,X) Poziv a@b se sada tumači kao: operator@(a,b) , za globalnu funkciju

class

complex {

double

real,imag;

public

: complex (

double

r=0,

double

i=0) : real(r), imag(i) {} complex

operator

+(complex c) {

return

complex(real+c.real,imag+c.imag; } }; // ili, alternativno:

class

complex {

double

real,imag;

public

: complex (

double

r=0,

double

i=0) : real(r), imag(i) {}

friend

complex

operator

+(complex,complex); }; complex

operator

+ (complex c1, complex c2) {

return

complex(c1.real+c2.real,c1.imag+c2.imag); }

void

} main () { complex c1(2,3),c2(3.4); complex c3=c1+c2; // poziva se c1.operator+(c2) ili operator+(c1,c2)

  Unarni operator ima samo jedan operand, pa se može realizovati: ◦ kao operatorska funkcija članica bez argumenata: tip operator@ () ◦ Binarni operator ima dva argumenta, pa se može realizovati: ◦ kao funkcija članica sa jednim argumentom: tip operator@ (X xdesni) ◦ kao globalna funkcija sa jednim argumentom: tip operator@ (X x) kao globalna funkcija sa dva argumenta: tip operator@ (X xlevi, X xdesni)

 ◦ ◦ Unarni operator može biti preklopljen kao: nestatička funkcija članica bez argumenata; ne može biti statička jer mora pristupati pojedinačnom atributu samostalna funkcija (nije funkcija članica) sa jednim argumentom (objekat ili referenca)

 ◦ ◦ Binarni operator može biti preklopljen kao: nestatička funkcija članica sa jednim argumentom samostalna funkcija sa dva argumenta (bar jedan mora biti objekat ili referenca na objekat)

class

complex { //...

public

: complex

operator

!();

friend

complex

operator~

(complex); complex

operator-

(complex); // članica unarni operator! // globalna f-ja, unarni operator~ // članica binarni operator-

friend

complex

operator

+(complex,complex); // globalna f-ja, binarni operator+ };

  ◦ ◦ ◦ Operatorske funkcije realizuju se kao funkcije članice klasa Operatorske funkcije se definišu kao javne i statičke metode klasa Ne mogu koristiti pokazivač this na objekat date klase Imaju jedan argument za unarne, dva za binarne operatore Najmanje jedan argument mora biti korisnički definisan tip (klasa, struktura)

} { public static Vector operator + (Vector lhs, Vector rhs) Vector result = new Vector(lhs); result.x += rhs.x; result.y += rhs.y; result.z += rhs.z; return result; } { public static Vector operator * (double lhs, Vector rhs) return new Vector(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z); } { public static double operator * (Vector lhs, Vector rhs) return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z;

    Postoji 6 relacionih operatora u jeziku C# i moraju se preklapati u parovima ◦ ◦ ◦ == i != > i < >= i <= Ako se izvrši preklapanje operatora ==, mora se preklopiti i operator !=, u protivnom kompajler prijavljuje grešku Slično važi za ostale relacione operatore Relacioni operatori vraćaju logičku vrijednost

   Ako se izvrši preklapanje operatora == i !=, moraju se predefinisati i funkcije

GetHashCode()

Funkcija

Equals() Equals()

i naslijeđene iz System.Object

treba da implementira istu logiku kao i operator jednakosti Ako se ne izvršti redefinisanje prethodne dvije metode, kompajler generiše upozorenje (ne grešku)

} { public static bool operator == (Vector lhs, Vector rhs) if (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z) return true; else return false; } { public static bool operator != (Vector lhs, Vector rhs) return ! (lhs == rhs);

  ◦ ◦ ◦ ◦ ◦ Implicitna konverzija Izvršava se automatski između kompatibilnih tipova upotrijebljenih u izrazima Eksplicitna konverzija Kada postoji rizik gubitka podataka ili pojave greške u konverziji Mora se eksplicitno navesti u izrazu Cast operator ( tip konverziju tipova ) se koristi za eksplicitnu Sintaksa: ( tip ) varijabla int i = 3; long j = i; // implicitna short s = (short)i; // eksplicitna

    Konverzija se definiše kao operatorska funkcija u okviru klase Može se definisati kao implicitna ili eksplicitna konverzija Uvijek definisati kao eksplicitnu konverziju u slučaju da postoji bilo kakva mogućnost greške pri konverziji Povratni tip operatorske funkcije jednak je operatoru konverzije } { public static implicit operator float (Currency value) return value.Dollars + (value.Cents/100.0f);

//primjer definisanja operatora konverzije za slučaj struktura //na isti način se radi sa klasama { struct Currency public uint Dollars; public ushort Cents; } { public static implicit operator float (Currency value) return value.Dollars + (value.Cents/100.0f); } ...

Currency balance = new Currency(10,50); float f = balance; //implicitna konverzija Currency u float

{ struct Currency public uint Dollars; public ushort Cents; } } { public static explicit operator Currency (float value) uint dollars = (uint)value; ushort cents = (ushort)((value-dollars)*100); return new Currency(dollars, cents); } ....

float amount = 45.63f; Currency amount2 = (Currency)amount; //eksplicitna konverzija Currency amount3 = amount; // greška

  ◦ ◦ Moguće je definisati konverzije između bilo koja dva korisnički definisana tipa (klase, strukture) Ograničenja Ne može se definisati konverzija za dvije klase ako je jedna izvedena iz druge klase Konverzija se mora definisati u okviru definicije izvorišne ili odredišne klase (tipa)

   Moguće je definisati konverziju samo između klasa C i D Operatorska funkcija za konverziju se definiše u okviru definicije klase C ili D, ne u obje Mora biti moguć pristup source kodu klasa C ili D da bi se realizovala konverzija Ograničenja Hijerarhija klasa

} { public static explicit operator D(C value) //implementacija konverzije } { public static explicit operator C(D value) //implementacija konverzije