RP 3predavanje 04 q Strukture q Delegati q

  • Slides: 47
Download presentation
RP 3/predavanje 04 q Strukture q Delegati q Događaji q Sučelja 17/09/2020 ----- Računarski

RP 3/predavanje 04 q Strukture q Delegati q Događaji q Sučelja 17/09/2020 ----- Računarski praktikum 3 ----- 1

Strukture Za razliku od klase koja je referentni tip, struktura je vrijednosni tip. Ne

Strukture Za razliku od klase koja je referentni tip, struktura je vrijednosni tip. Ne podržava nasljeđivanje. Varijable članice se ne mogu inicijalizirati unutar strukture. Struktura može sadržavati sve članove kao i klasa osim: q konstruktora bez parametara q finalizatora q virtualnih (i apstraktnih) članova Napomena: konstruktor bez parametara je implicitno definiran i ne može se redefinirati. Dakle, nije moguće spriječiti instanciranje strukture tako da se svi konstruktori učine privatnima (kao kod klasa). 17/09/2020 -------Računarski praktikum 3 ------- 2

Strukture Struktura se općenito definira na sljedeći način: [attributi] [modifikatori] struct identifikator [: sučelja]

Strukture Struktura se općenito definira na sljedeći način: [attributi] [modifikatori] struct identifikator [: sučelja] { tijelo strukture }[; ] 17/09/2020 -------Računarski praktikum 3 ------- 3

Konstruktor strukture Implicitno je definiran konstruktor koji ne prima parametre i koji se ne

Konstruktor strukture Implicitno je definiran konstruktor koji ne prima parametre i koji se ne može redefinirati. Pri definiciji konstruktora mora se eksplicitno dodijeliti vrijednost svakoj varijabli. U strukturi se varijable članice ne mogu inicijalizirati pri deklaraciji. public struct Point { public int x, y; public Point (int x, int y) { this. x=x; this. y=y; } } 17/09/2020 -------Računarski praktikum 3 ------- 4

Konstruktor strukture Primjer pogrešno definirane strukture: public struct Point { public int x=0; //

Konstruktor strukture Primjer pogrešno definirane strukture: public struct Point { public int x=0; // nedozvoljeno, inicijalizacija pri deklaraciji public int y; public Point( ) { } // konstruktor bez parametara se ne može definirati (definiran je implicitno) public Point(int x) { this. x=x; // greška, unutar konstruktora potrebno je inicijalizirati sve varijable } } 17/09/2020 -------Računarski praktikum 3 ------- 5

Strukture i nasljeđivanje Strukture ne podržavaju nasljeđivanje. Drugim riječima, struktura se ne može izvesti

Strukture i nasljeđivanje Strukture ne podržavaju nasljeđivanje. Drugim riječima, struktura se ne može izvesti ni iz klase ni iz druge strukture. Može samo naslijediti jedno ili više sučelja. Dakle, struktura ne može biti apstraktna. Struktura je uvijek implicitno zaštićena (greška je eksplicitno navesti modifikator sealed). U strukturi dakle ne nalazimo apstraktne i virtualne metode, dok se mogu nadjačavati samo metode definirane u klasi object koju struktura implicitno nasljeđuje. 17/09/2020 -------Računarski praktikum 3 ------- 6

Delegati delegate int Racunska. Operacija( int x ); class Test { static void Main()

Delegati delegate int Racunska. Operacija( int x ); class Test { static void Main() { Racunska. Operacija r = Kvadriranje; // ili …. . Deklaracija tipa delegata Kreiranje instance delegata Racunska. Operacija r = new Racunska. Operacija(Kvadriranje); Console. Write. Line( r(3) ); } static int Kvadriranje (int x) { return x*x; } Metoda koja odgovara tipu delegata } 17/09/2020 Računarski praktikum 3 7

Delegati Primjer: parametar funkcije je tipa delegat. static int Kvadriranje ( int x )

Delegati Primjer: parametar funkcije je tipa delegat. static int Kvadriranje ( int x ) { return (x * x); } delegate int Racunska. Operacija( int x ); class Program { public static int Racunaj(int broj, Racunska. Operacija operacija) { return operacija(broj); } static int Kubiranje (int x) { return (x*x*x); } } static void Main(string[] args) { Console. Write. Line(Racunaj(3, Kvadriranje)); } 17/09/2020 Računarski praktikum 3 8

Delegati Svi delegati su višeodredišni, tj. instance delegata mogu referirati na više ciljanih metoda.

Delegati Svi delegati su višeodredišni, tj. instance delegata mogu referirati na više ciljanih metoda. To se postiže upotrebom operatora +=. Racunska. Operacija r = Kvadriranje; r += Kubiranje; Pozivanjem instance delegata, pozvat će se sve metode koje su joj dodijeljene i to onim redoslijedom kojim su dodijeljene. 17/09/2020 Računarski praktikum 3 9

Delegati static int Kvadriranje(int x) { return (x * x); } delegate int Racunska.

Delegati static int Kvadriranje(int x) { return (x * x); } delegate int Racunska. Operacija (int x); class Program { static void Main(string[] args) { Racunska. Operacija r = Kvadriranje; r += Kubiranje; static int Kubiranje(int x) { return (x * x ); } } Console. Write. Line( r(3) ); } Output: 27 17/09/2020 Računarski praktikum 3 10

Delegati static void Kvadriranje(int x) { Console. Write. Line (x * x); } delegate

Delegati static void Kvadriranje(int x) { Console. Write. Line (x * x); } delegate void Racunska. Operacija (int x); class Program { static void Main(string[] args) { Racunska. Operacija r = Kvadriranje; r += Kubiranje; static void Kubiranje(int x) { Console. Write. Line (x * x ); } } r(3); } Output: 9 27 17/09/2020 Računarski praktikum 3 11

Delegati Delegat može sadržavati parametre generičkog tipa. class Program { public delegate T Racunska.

Delegati Delegat može sadržavati parametre generičkog tipa. class Program { public delegate T Racunska. Operacija<T> (T arg); static double Kvadriranje(double x) { return x * x; } static void Main(string[ ] args) { Racunska. Operacija<double> r=Kvadriranje; Console. Write. Line( r(2. 5) ); } } 17/09/2020 Računarski praktikum 3 12

Delegati su inkompatibilni, čak i ako imaju isti potpis. delegate void D 1( );

Delegati su inkompatibilni, čak i ako imaju isti potpis. delegate void D 1( ); delegate void D 2( ); D 1 d 1=Metoda 1; D 2 d 2=d 1; // greška Instance delegata su jednake ako imaju iste ciljne metode. delegate void D( ); D d 1=Metoda 1; D d 2=Metoda 1; Console. Write. Line(d 1==d 2); 17/09/2020 Računarski praktikum 3 //True 13

Delegati public delegate void Neki. Delegat(); public class Program { public static void Metoda

Delegati public delegate void Neki. Delegat(); public class Program { public static void Metoda 1( ) { Console. Write. Line("Metoda 1"); } public static void Metoda 2( ) { Console. Write. Line("Metoda 2"); } public static void Metoda 3( ) { Console. Write. Line("Metoda 3"); } public static void Metoda 4( ) { Console. Write. Line("Metoda 4"); } 17/09/2020 Računarski praktikum 3 14

Delegati static void Main(string[] args) { Neki. Delegat d = Metoda 1; d +=

Delegati static void Main(string[] args) { Neki. Delegat d = Metoda 1; d += Metoda 2; d += Metoda 3; d -= Metoda 3; d += Metoda 4; d += Metoda 2; d += Metoda 4; d -= Metoda 2; d( ); } } 17/09/2020 Računarski praktikum 3 15

Delegati static void Main(string[] args) { Neki. Delegat d = Metoda 1; d +=

Delegati static void Main(string[] args) { Neki. Delegat d = Metoda 1; d += Metoda 2; d += Metoda 3; d -= Metoda 3; d += Metoda 4; d += Metoda 2; d += Metoda 4; d -= Metoda 2; d( ); Output: Metoda 1 Metoda 2 Metoda 3 Metoda 2 Metoda 4 } } 17/09/2020 Računarski praktikum 3 16

Događaji omogućavaju da objekt koji obavještava o nekoj promjeni do koje je došlo, ne

Događaji omogućavaju da objekt koji obavještava o nekoj promjeni do koje je došlo, ne mora znati ništa o objektima koje obavještava, tj. ne treba imati referencu na njih. Slušatelji se mogu po potrebi prijavljivati i odjavljivati. Događaj je omotač oko delegata koji sprječava sukobljavanje slušatelja. 17/09/2020 Računarski praktikum 3 17

Događaji Izvan objekta izvjestitelja prijavljivanje metoda za događaj može se vršiti samo pomoću operatora

Događaji Izvan objekta izvjestitelja prijavljivanje metoda za događaj može se vršiti samo pomoću operatora +=. Ako ispustimo ključnu riječ event, program i dalje daje isti rezultat, ali u tom slučaju neki od slušatelja mogu ometati druge na način da: o u potpunosti zamijene sve ostale slušatelje koji su se prethodno prijavili za obrađivanje događaja o izbrišu sve prijavljene slušatelje o izvještavaju druge slušatelje o događaju 17/09/2020 Računarski praktikum 3 18

Događaji Zadatak: pronađite greške u kodu. public delegate void Neki. Delegat(); public class Test

Događaji Zadatak: pronađite greške u kodu. public delegate void Neki. Delegat(); public class Test { public class Program { public void test() { Console. Write. Line("test"); } public Neki. Delegat d; public event Neki. Delegat e; static void Main(string[ ] args) { Program p = new Program( ); Test t = new Test( ); t. d = p. test; t. e = p. test; t. d( ); t. e( ); public void f( ) { Program p = new Program( ); p. test( ); d( ); e( ); } } 17/09/2020 Računarski praktikum 3 19

Događaji public delegate void Neki. Delegat(); public class Test { public class Program {

Događaji public delegate void Neki. Delegat(); public class Test { public class Program { public void test() { Console. Write. Line("test"); } public Neki. Delegat d; public event Neki. Delegat e; static void Main(string[ ] args) { Program p = new Program( ); Test t = new Test(); t. d = p. test; // u redu je i…. . t. d += p. test; t. e = p. test; // greška ( t. e += p. test; ) t. d( ); t. e( ); // obavještavanje o događaju je dozvoljeno samo unutar klase Test } public void f( ) { Program p = new Program( ); p. test( ); d( ); e( ); } } } 17/09/2020 Računarski praktikum 3 20

Događaji Primjer (pritisak na tipku): U klasi System. Windows. Forms. Button definiran je događaj

Događaji Primjer (pritisak na tipku): U klasi System. Windows. Forms. Button definiran je događaj public event Event. Handler Click; koji se obrađuje uz pomoć delegata (iz prostora System) public delegate void Event. Handler (object sender, Event. Args e); 17/09/2020 Računarski praktikum 3 21

Događaji Moguće je koristiti i generički delegat: public delegate void Event. Handler<TEvent. Args> (object

Događaji Moguće je koristiti i generički delegat: public delegate void Event. Handler<TEvent. Args> (object sender, TEvent. Args e) where TEvent. Args : Event. Args; Event. Args je temeljna klasa koja pruža informacije o događaju. Sadrži samo statičko Empty svojstvo. 17/09/2020 Računarski praktikum 3 22

Događaji Primjer 1: Kad u instanci klase Student dođe do promjene vrijednosti varijable ime,

Događaji Primjer 1: Kad u instanci klase Student dođe do promjene vrijednosti varijable ime, objekt odašilje obavijest o događaju Promjena. Imena. Taj događaj obrađuje metoda Obavijesti koja se prethodno prijavila za taj događaj preko delegata Promjena. Imena. Handler. 17/09/2020 Računarski praktikum 3 23

Događaji. public delegate void Promjena. Imena. Handler(string s); public string Ime { get {

Događaji. public delegate void Promjena. Imena. Handler(string s); public string Ime { get { return ime; } set { if (ime != value) { ime = value; Promjena. Imena(ime); } } } class Student { string ime; string prezime; public event Promjena. Imena. Handler Promjena. Imena; public Student(string ime) { this. ime = ime; } } Objavljivanje događaja 17/09/2020 Računarski praktikum 3 24

Događaji class Program { public static void Obavijesti(string novo. Ime) { Console. Write. Line("Ime

Događaji class Program { public static void Obavijesti(string novo. Ime) { Console. Write. Line("Ime je promijenjeno u "+novo. Ime); } static void Main(string[] args) { Student s = new Student("Lana"); s. Promjena. Imena += new Promjena. Imena. Handler(Obavijesti); s. Ime = "Ana"; } Prijava za događaj } 17/09/2020 Računarski praktikum 3 25

Delegate je bazna klasa za sve delegatske tipove. Radi se o apstraktnoj klasi iz

Delegate je bazna klasa za sve delegatske tipove. Radi se o apstraktnoj klasi iz koje ne možemo u izvoditi vlastite klase. Preciznije, svi delegati su izvedeni iz klase Multi. Cast. Delegate koja je bazna klasa za višeodredišne delegate, a ta klasa je izvedena iz klase Delegate. U sljedećem primjeru ćemo vidjeti kako djeluju neke metode iz klase Delegate: 17/09/2020 Računarski praktikum 3 26

Delegate class Program { public delegate void Moj. Delegat(); public static void Metoda 1()

Delegate class Program { public delegate void Moj. Delegat(); public static void Metoda 1() { Console. Write("m 1 "); } public static void Metoda 2() { Console. Write("m 2 "); } 17/09/2020 Računarski praktikum 3 27

Delegate static void Main(string[] args) { Moj. Delegat d 1 = Metoda 1; Moj.

Delegate static void Main(string[] args) { Moj. Delegat d 1 = Metoda 1; Moj. Delegat d 2 = Metoda 2; Moj. Delegat d 3 = (Moj. Delegat)Delegate. Combine(d 1, d 2, d 1); d 3( ); Console. Write("---"); Moj. Delegat d 4 = (Moj. Delegat)Delegate. Remove(d 3, d 2); d 4( ); Console. Write("---"); Moj. Delegat d 5 = (Moj. Delegat)Delegate. Remove. All(d 3, d 1); d 5( ); Console. Write("---"); Moj. Delegat d 6 = (Moj. Delegat)Delegate. Combine(d 4, d 5); d 6(); } } // m 1 m 2 m 1 --- m 1 m 2 m 1 m 1 --- m 2 m 2 --- m 1 m 2 m 1 m 1 m 2 m 2 17/09/2020 Računarski praktikum 3 28

Add, remove public delegate void Moj. Delegat(); public class C { public event Moj.

Add, remove public delegate void Moj. Delegat(); public class C { public event Moj. Delegat e; } U prethodnom primjeru je kompilator deklaraciju događaja e konvertirao u: q privatnu varijablu tipa Moj. Delegat i q javni par pristupnih funkcija (add, remove) 17/09/2020 Računarski praktikum 3 29

Add, remove Dakle, prethodni kod je ekvivalentan sljedećem: public delegate void Moj. Delegat(); public

Add, remove Dakle, prethodni kod je ekvivalentan sljedećem: public delegate void Moj. Delegat(); public class C { private Moj. Delegat d; public event Moj. Delegat e { add { d+= value; } remove { d-=value; } } // Nap: potrebno je implementirati // oba pristupnika } 17/09/2020 Računarski praktikum 3 30

Add, remove public delegate void Moj. Delegat(); class C { private Moj. Delegat d;

Add, remove public delegate void Moj. Delegat(); class C { private Moj. Delegat d; public event Moj. Delegat e { add { Console. Write. Line("Dodajemo metodu"); d += value; } remove { Console. Write. Line("Oduzimamo metodu"); d -= value; } } public void objavi() { //e(); greška d(); } } class Program { public static void f() { Console. Write. Line("Obradjujemo dogadjaj"); } static void Main(string[] args) { C c = new C(); c. e += f; c. e -= f; c. objavi(); } } Dodajemo metodu Oduzimamo metodu Obradjujemo dogadjaj 17/09/2020 Računarski praktikum 3 31

Sučelja Sintaksa sučelja je [ atributi ] [ modifikatori pristupa ] interface Ime. Sučelja

Sučelja Sintaksa sučelja je [ atributi ] [ modifikatori pristupa ] interface Ime. Sučelja [: sučelja] { tijelo sučelja } Sučelje za razliku od klasa pruža specifikaciju svojih članova, a ne implementaciju. Klasa može implementirati više sučelja. 17/09/2020 -------Računarski praktikum 3 ------- 32

Sučelja Svi članovi sučelja su (implicitno) apstraktni. Greška je eksplicitno navoditi modifikator pristupa. S

Sučelja Svi članovi sučelja su (implicitno) apstraktni. Greška je eksplicitno navoditi modifikator pristupa. S druge strane, (apstraktne) klase mogu sadržavati i apstraktne i implementirane članove. Strukture mogu implementirati sučelja, ali ne mogu naslijediti klasu. Sučelja mogu sadržavati metode, svojstva, događaje i indeksere (to su ujedno i članovi klase koji mogu biti apstraktni). Pod implementacijom sučelja podrazumijeva se public implementacija svih njegovih članova. 17/09/2020 -------Računarski praktikum 3 ------- 33

Sučelja interface IPokretljivo { class Auto : IPokretljivo { bool u. Voznji; void Pokreni();

Sučelja interface IPokretljivo { class Auto : IPokretljivo { bool u. Voznji; void Pokreni(); void Zaustavi(); public void Pokreni() { u. Voznji = true; } } public void Zaustavi() { u. Voznji = false; } } 17/09/2020 -------Računarski praktikum 3 ------- 34

Sučelja Klase mogu implementirati i više sučelja. interface IUpaljivo { void Upali( ); void

Sučelja Klase mogu implementirati i više sučelja. interface IUpaljivo { void Upali( ); void Ugasi( ); } class Auto : IPokretljivo, IUpaljivo { public void Pokreni( ) { //implementacija } public void Zaustavi( ) { //implementacija } Moramo dodati i ove implementacije. public void Upali( ) { //implementacija } public void Ugasi( ) { //implementacija } } 17/09/2020 -------Računarski praktikum 3 ------- 35

Sučelja Sučelje se može izvesti iz nekog drugog sučelja i pritom nasljeđuje sve njegove

Sučelja Sučelje se može izvesti iz nekog drugog sučelja i pritom nasljeđuje sve njegove članove. interface IVozilo: IPokretljivo { void Upali(); void Ugasi(); } U prethodnom primjeru sučelje IVozilo dakle proširuje sučelje IPokretljivo. 17/09/2020 -------Računarski praktikum 3 ------- 36

Sučelja class Auto : IVozilo { bool u. Voznji; bool upaljeno; public void Upali()

Sučelja class Auto : IVozilo { bool u. Voznji; bool upaljeno; public void Upali() { upaljeno = true; } public void Pokreni() { u. Voznji = true; } public void Ugasi() { upaljeno = false; } } public void Zaustavi() { u. Voznji = false; } 17/09/2020 -------Računarski praktikum 3 ------- 37

Sučelja interface I 1 { … } interface I 2 : I 1 {

Sučelja interface I 1 { … } interface I 2 : I 1 { … } class C : I 2 { … } class Program { static void Main(string[] args) { C c = new C(); I 1 i 1 = c; I 2 i 2 = c; i 1 = i 2; // i 2 = i 1; greška i 2=(I 2)i 1; } } 17/09/2020 -------Računarski praktikum 3 ------- 38

Sučelja Dozvoljena je i ovakva definicija varijable: IPokretljivo auto 1=new Auto(); // auto 1.

Sučelja Dozvoljena je i ovakva definicija varijable: IPokretljivo auto 1=new Auto(); // auto 1. Upali(); auto 1. Pokreni(); ((Auto)auto 1). Upali(); Metode kao povratni tip mogu imati i sučelje. To je apstraktniji način definiranja metode. Označava da metoda kao povratni tip prima bilo koju klasu (ili strukturu ) koja implementira zadano sučelje. 17/09/2020 -------Računarski praktikum 3 ------- 39

Sučelja U sljedećem primjeru sučelje sadrži događaj. public delegate void Delegat(); public interface I

Sučelja U sljedećem primjeru sučelje sadrži događaj. public delegate void Delegat(); public interface I { event Delegat e; // Delegat d; void Objavi(); } 17/09/2020 U sučelju se ne može nalaziti delegat! -------Računarski praktikum 3 ------- 40

Sučelja public class C : I { public event Delegat e; /* ovaj redak

Sučelja public class C : I { public event Delegat e; /* ovaj redak može predstavljati implementaciju događaja */ public class Program { static private void f() { Console. Write. Line("Dogodio se dogadjaj : ). "); } public void Objavi() { if (e != null) e(); } static public void Main() { I i = new C(); // sad sve možemo izvršiti i preko sučelja i. e += f; i. Objavi(); } } } 17/09/2020 -------Računarski praktikum 3 ------- 41

Sučelja Primjer: implementacija svojstva i indeksera iz sučelja. public interface I { int Broj

Sučelja Primjer: implementacija svojstva i indeksera iz sučelja. public interface I { int Broj { get; set; } int this[int index] { get; set; } } Napomena: sučelje može zahtijevati da se implementira samo jedan od pristupnika, međutim to ne sprječava klasu u implementaciji drugog pristupnika. 17/09/2020 -------Računarski praktikum 3 ------- 42

Sučelja public class C : I { public int this[int index] { get {

Sučelja public class C : I { public int this[int index] { get { return niz[index]; } public int Broj { get { return broj; } set { niz[index] = value; } set { broj = value; } } private int broj; private int[] niz=new int[10]; } } 17/09/2020 -------Računarski praktikum 3 ------- 43

Sučelja U dosadašnjim primjerima klasa je implementirala metodu iz sučelja implicitno. Klasa ili struktura

Sučelja U dosadašnjim primjerima klasa je implementirala metodu iz sučelja implicitno. Klasa ili struktura mogu implementirati više sučelja koja sadrže metodu s istim potpisom. U tom slučaju, ako želimo imati različite implementacije, možemo metodu implementirati i eksplicitno. Pritom se ne navodi modifikator pristupa. Da bi se takva metoda pozvala, potrebno je kastati varijablu tipa klase u tip sučelja. 17/09/2020 -------Računarski praktikum 3 ------- 44

Sučelja interface I 1 { void f( ); } interface I 2 { void

Sučelja interface I 1 { void f( ); } interface I 2 { void f( ); } interface I 3 { void f( ); } class C : I 1, I 2, I 3 { public void f() { Console. Write(“Prva f”); } class Program { static void Main(string[] args) { C cobj = new C(); cobj. f(); I 2 i 2 = cobj; i 2. f(); } } void I 2. f(){ Console. Write(“Druga f”); } void I 3. f() { Console. Write(“Treca f”); } //eksplicitne implementacije } 17/09/2020 -------Računarski praktikum 3 ------- 45

Sučelja Ako želimo metodu koja implementira sučelje označiti kao virtualnu, ta metoda mora implicitno

Sučelja Ako želimo metodu koja implementira sučelje označiti kao virtualnu, ta metoda mora implicitno implementirati sučelje. Nadjačavanje takve metode se radi standardno pomoću ključne riječi override. U izvedenoj klasi može se napraviti reimplementacija metode iz bazne klase koja implementira sučelje, bilo da se pritom radi o eksplicitnoj ili implicitnoj implementaciji. 17/09/2020 -------Računarski praktikum 3 ------- 46

Sučelja interface I { void f(); void g(); void h(); } class B :

Sučelja interface I { void f(); void g(); void h(); } class B : A { public override void f(){ onsole. Write. Line("B"); } public new void g() { Console. Write. Line("B"); } public new void h() { Console. Write. Line("B"); } class A : I { } public virtual void f() { Console. Write. Line("A"); } void I. g() { Console. Write. Line("A"); } public void h() { Console. Write. Line("A"); } } 17/09/2020 class Program { static void Main(string[] args) { B b= new B(); b. f(); ((A)b). f(); ((I)b). f(); // B B B b. g(); ((I)b). g(); //((A)b). g(); // B A b. h(); ((A)b). h(); ((I)b). h(); // B A A } } -------Računarski praktikum 3 ------- 47