160 likes | 257 Views
Računarski praktikum 3 Vježbe 04. Vinko Petričević. Sučelja. Sučelja (interface). C# ne podržava višestruko nasljeđivanje klasa, međutim svaka klasa/struktura može zadovoljavati više sučelja sučelje je ugovor koji nam garantira da se klasa ‘zna’ ponašati na određeni način
E N D
Računarski praktikum 3Vježbe 04 Vinko Petričević Sučelja
Sučelja (interface) • C# ne podržava višestruko nasljeđivanje klasa, međutim svaka klasa/struktura može zadovoljavati više sučelja • sučelje je ugovor koji nam garantira da se klasa ‘zna’ ponašati na određeni način • sučelje možemo shvatiti kao čisto-apstraktnu klasu, koja može imati metode, svojstva, indeksere i događaje, ali ne može imati varijable
Interface • struktura je vrijednosti tip • modifikator pristupa isti kao kod klasa • uobičajeno je nazive interfacea započimati velikim I (IStorable, IDisposable…) • tijelo opisuje metode koje implementirajuća klasa treba implementirati • nema modifikatora pristupa – sve je public • nema implementacije metoda [pristup] interfacenaziv [: popis osnovnih sučelja] { // tijelo sučelja }
Primjer sučelja interface IPohranjivo { objectCitaj(); voidPisi(objecto); intStatus { get; set; } } // deklaracija klase koja implementira sučelje IPohranjivo class Osoba : IPohranjivo { // implementacija sučelja publicobjectCitaj() { Console.WriteLine("Implementacija metode Citaj() iz IPohranjivo"); return"Nesto je procitano"; } publicvoidPisi(objecto) { Console.WriteLine("Implementacija metode Pisi() iz IPohranjivo"); } privateintstatus = 0; // sprema vrijednost za svojstvo publicintStatus { get { returnstatus; } set { status = value; } } // Ostatak implementacije klase publicstringIme, Prezime; publicOsoba(string ime, stringprezime) { this.Ime = ime; this.Prezime = prezime; } } • konstruktori se ne nasljeđuju. ako nemamo defaultni konstruktor, moramo ga pozvati eksplicitno
Pretvaranje u sučelje • Instancu sučelja ne možemo izravno stvoriti, ali možemo stvoriti instancu klase koja implementira sučelje, te ju pretvoriti u sučelje • dogodila se implicitna pretvorba: • metode sučelja pozivamo kao da se radi o klasi Osobao = newOsoba("Ivan", "Ivanković"); IPohranjivoipOsoba = o; IPohranjivoipOsoba = (IPohranjivo) o; ipOsoba.Status = 0; ipOsoba.Citaj();
Pretvaranje u sučelje • Instancu sučelja ne možemo izravno stvoriti, ali možemo stvoriti instancu klase koja implementira sučelje, te ju pretvoriti u sučelje • implicitna pretvorba: • eksplicitna pretvorba void f(IPohranjivo ip) { ... } Osobao = newOsoba("Ivan", "Ivanković"); IPohranjivoipOsoba = o; f(o); objectobj =o; f((IPohranjivo)obj);
Primjer sučelja interface IPohranjivo { objectCitaj(); voidPisi(objecto); intStatus { get; set; } } • nije toliko bitno kako klasa implementira metode • bitno je da da ih implementira sve class Osoba : IPohranjivo { publicobjectCitaj() { ... } publicvoidPisi(objecto) { ... } publicintStatus { get { ... } set { ... } } }
Implementiranje više sučelja class Osoba : IPohranjivo, IKompresibilno • sada klasa Osoba mora implementirati oba sučelja • novo sučelje sada ima sve metode oba sučelja interface IBiljezivoKompresibilno : IKompresibilno { void ZabiljeziPohranjeneBajtove(); } interface IPohranjivoKompresibilno : IPohranjivo, IBiljezivoKompresibilno { void ZabiljeziOriginalnuVelicinu(); }
Operator as i is ISifrabilno isOsoba = o; // implicitna pretvorba ISifrabilno isOsoba = (ISifrabilno)o; // eksplicitna pretvorba pomoću cast operatora ISifrabilno isOsoba = o as ISifrabilno; // pretvorba pomoću operatora as • kao dynamic_cast • ako samo želimo provjeriti je li moguće tip pretvoriti, možemo koristiti operator is ISifrabilno isOsoba = o as ISifrabilno; if (isOsoba != null) ... if (o is ISifrabilno) …
apstraktne klase i interface interface IPohranjivo { void Citaj(); void Pisi(object o); int Status { get; set; } } • vrlo slično, ipak kod apstraktne klase nema višestrukog nasljeđivanja abstract class Pohranjivo { abstract public void Citaj(); abstract public void Pisi(object o); abstract public int Status { get; set; } }
premošćivanje implementacije • implementirajuća klasa može neke metode sučelja označiti kao virtualne. Tada izvedene klase mogu premostiti te implementacije interface IPohranjivo { void Citaj(); } class Osoba : IPohranjivo { public virtual void Citaj() { Console.WriteLine("Implementacija metode Citaj() u klasi Osoba"); } } class Student : Osoba { public override void Citaj() { Console.WriteLine("Premošćena metoda Citaj() u klasi Student"); } }
Zadatak 1 • Napišite sučelje IPovrsina koje racuna povrsinu • Napišite sučelje IOpseg koje racuna opseg • Napišite klasu lik. Iz te klase izvedite klasu trokut, cetverokut, kvadrat, te krug • napisite program koji ispisuje povrsinu i opseg danog lika (ako je to moguce)
Eksplicitna implementacija • ako više sučelja ima istu metodu interface IPohranjivo { void Citaj(); void Pisi(); } interface IPrevodljivo { void Citaj(); void Prevedi(); } class Osoba : IPohranjivo, IPrevodljivo { public virtual void Citaj() { Console.WriteLine("Implementacija IPohranjivo.Citaj()"); } public void Pisi() { …. } void IPrevodljivo.Citaj() { Console.WriteLine("Implementacija IPrevodljivo.Citaj()"); } public void Prevedi() { …. } }
Eksplicitna implementacija • kod eksplicitne implementacija nema modifikatora pristupa, ona je javna. Ne možemo staviti ni obstract, virtual, override ili new. • pozivamo ih preko reference sučelja class Program { static void Main(string[] args) { Osoba o = new Osoba(); IPohranjivo ipohranjivoOsoba = o; ipohranjivoOsoba.Citaj(); IPrevodljivo iprevodljivoOsoba = o; iprevodljivoOsoba.Citaj(); o.Citaj(); // poziva se metoda sučelja IPohranjivo } }
Implementacija u strukturi • bolje pozivati direktno, jer se prilikom pretvorbe u interface vrši pakiranje, pa se mijenja zapakirani objekt, a ne sama struktura interface IPohranjivo{ void Citaj(); int Status { get; set; } } public struct TestStruct : IPohranjivo { public void Citaj() { Console.WriteLine("Implementacija IPohranjivo.Citaj()"); } private int status; public int Status { get { return status; } set { status = value; } } }
Implementacija u strukturi static void Main(string[] args) { // stvaramo instancu strukture TestStruct ts = new TestStruct(); ts.Status = 0; // inicijaliziramo svojstvo Console.WriteLine("Instanca inicijalizirana."); Console.WriteLine("ts.Status: {0}", ts.Status); // mijenjamo vrijednost instanci ts.Status = 1; Console.WriteLine("Instanca promijenjena."); Console.WriteLine("ts.Status: {0}", ts.Status); // pretvaramo u IPohranjivo (implicitno pakiranje u referentni tip) IPohranjivo ipTemp = (IPohranjivo)ts; // postavljamo novu vrijednost kroz referencu sučelja ipTemp.Status = 2; Console.WriteLine("Sučelje promijenjeno."); Console.WriteLine("ts.Status: {0}, ipTemp.Status: {1}", ts.Status, ipTemp.Status); // ponovno mijenjamo vrijednost instanci ts.Status = 3; Console.WriteLine("Instanca promijenjena."); Console.WriteLine("ts.Status: {0}, ipTemp.Status: {1}“, ts.Status, ipTemp.Status); }