Polimorfizam u nasleđivanju

Do sada smo se susreli sa 4 vrste polimorfizma.

1) Polimorfizam promenljive

2) Polimorfizam funkcija (preopterećivanje (overloading) funkcija) 

3) Polimorfizam klasa. Mogu da postoje klase sa istim nazivom ali je važno da se nalaze u okviru različitog imenskog prostora

4) Polimorfizam operatora. 

Polimorfizam u nasleđivanju može da se realizuje na tri načina. 

1) U nasleđenoj klasi se piše nova funkcija sa istim nazivom kao i u osnovnoj klasi ali se razlikuje po broj ili tipu argumenata. 

2) Metoda u nasleđenoj klasi ima isti broj argumenata koji su istog tipa kao i metoda u osnovnoj klasi. 

3) Korišćenjem virutelnih metoda (radićemo kasnije)

class Pravougaonik
{
    protected int a;
    protected int b;

    public Pravougaonik():this(1,1){ }

    public Pravougaonik(int a, int b) 
    {
        Console.WriteLine("Pravljenje pravougaonika");
        this.a = a;
        this.b = b; 
    }

    public void SetStranica(int a, int b)
    {
         this.a = a;
         this.b = b;
         Console.WriteLine("Nove stranice pravougaonika su a:{0} i b:{1}", a,b);
    }

    public void Obim()
    {
        int O =  2*(a + b);
        Console.WriteLine("Obim pravougaonika je:{0}",O);
    }

    public void Povrsina()
    {
         int P = a*b;
         Console.WriteLine("Povrsina pravougaonika je:{0}", P);
    }
}
class Kvadrat:Pravougaonik
{ 
    public Kvadrat()
    {
        Console.WriteLine("Pravljenje kvadrata");
    }

    public Kvadrat(int a) : base(a, a)
    {
         Console.WriteLine("Pravljenje kvadrata");
    }

    public void SetStranica(int a)
    {
         this.a = a;
         Console.WriteLine("Nove stranica kvadrata je a:{0}", a);
    }

    public new void Obim()
    {
          int O = 4*a;
          Console.WriteLine("Obim kvadrata je:{0}", O);
    }

    public new void Povrsina()
    {
          int P = a * a;
          Console.WriteLine("Povrsina kvadrata je:{0}", P);
    }
}
class Program
{
   static void Main(string[] args)
   {
      Pravougaonik p = new Pravougaonik();
      p.Obim();
      p.Povrsina();
      //pozivaju se metode bazne klase
      Console.WriteLine();
            
      Kvadrat k = new Kvadrat();
      k.Obim();
      k.Povrsina();
      //pozivaju se metode izvede klase
      Console.WriteLine();

      Pravougaonik p1 = new Pravougaonik(5, 6);
      p1.Obim();
      p1.Povrsina();
      p1.SetStranica(10, 8);
      p1.Obim();
      p1.Povrsina();
      //pozivaju se metode bazne klase
      Console.WriteLine();

      ...      
      
   ...
   Kvadrat k1 = new Kvadrat(5);
   k1.Obim();
   k1.Povrsina();
   k1.SetStranica(8, 2);
   k1.Obim();
   k1.Povrsina();
   k1.SetStranica(9);
   k1.Obim();
   k1.Povrsina();
   //pozivaju se metode izvedene klase 
   //sem k.SetStranica(8, 2); tada se poziva
   //metoda bazne klase
   Console.WriteLine();

   Pravougaonik p2 = new Kvadrat(5);
   p2.Obim();
   p2.Povrsina();
   p2.SetStranica(8, 7);
   p2.Obim();
   p2.Povrsina();
   //pozivaju se metode bazne klase
   
   Console.ReadKey();
   }
}

Objekti nasleđene klase mogu da budu stvarni argumenti funkcija ukoliko su formalni argumenti funkcija objekti osnovne klase.

//Primer (klase kvadrat i pravougaonik su iz prethodnog primera):
class Program
{
    static void Main(string[] args)
    {
        Kvadrat k = new Kvadrat(8);
        nesto(k);
        Console.ReadKey();
    }

    static void nesto(Pravougaonik p)
    {
            p.Povrsina();
    }
}

VIRTUELNE METODE

3) Treći način realizacije polimorfizma u nasleđivanju jeste korišćenje virtuelnih metoda. 

Virtuelne metode se definišu u baznoj klasi.

Za definisanje virtuelne metode koristi se ključna reč virtual.

Virtualne funkcije se mogu defininisati drugačije u nasleđenoj klasi korišćenjem ključne reči override.

Virtual i override funkcije moraju da imaju : isti naziv, isti modifikator pristupa (protected, public, private ), istu povratnu vrednost ( void, string, int, float, double, itd ...), iste argumente (po broju i tipu), različit algoritam ali sličnu svrhu.

class Pravougaonik
{
    protected int a;
    protected int b;

    public Pravougaonik():this(1,1){ }

    public Pravougaonik(int a, int b) 
    {
       Console.WriteLine("Pravljenje pravougaonika");
       this.a = a;
       this.b = b; 
    }

    public void SetStranica(int a, int b)
    {
        this.a = a;
        this.b = b;
        Console.WriteLine("Nove stranice pravougaonika su a:{0} i b:{1}", a,b);
    }

    public virtual void Obim()
    {
         int O =  2*(a + b);
         Console.WriteLine("Obim pravougaonika je:{0}",O);
    }

    public virtual void Povrsina()
    {
          int P = a*b;
          Console.WriteLine("Povrsina pravougaonika je:{0}", P);
    }
}
class Kvadrat:Pravougaonik
{ 
    public Kvadrat()
    {
        Console.WriteLine("Pravljenje kvadrata");
    }

    public Kvadrat(int a) : base(a, a)
    {
         Console.WriteLine("Pravljenje kvadrata");
    }

    public void SetStranica(int a)
    {
         this.a = a;
         Console.WriteLine("Nove stranica kvadrata je a:{0}", a);
    }

    public override void Obim()
    {
          int O = 4*a;
          Console.WriteLine("Obim kvadrata je:{0}", O);
    }

    public override void Povrsina()
    {
          int P = a * a;
          Console.WriteLine("Povrsina kvadrata je:{0}", P);
    }
}
class Program
{
   static void Main(string[] args)
   {
      Pravougaonik p = new Pravougaonik();
      p.Obim();
      p.Povrsina();
      //pozivaju se metode bazne klase
      Console.WriteLine();
            
      Kvadrat k = new Kvadrat();
      k.Obim();
      k.Povrsina();
      //pozivaju se metode izvede klase
      Console.WriteLine();

      Pravougaonik p1 = new Pravougaonik(5, 6);
      p1.Obim();
      p1.Povrsina();
      p1.SetStranica(10, 8);
      p1.Obim();
      p1.Povrsina();
      //pozivaju se metode bazne klase
      Console.WriteLine();

      ...      
      
   ...
   Kvadrat k1 = new Kvadrat(5);
   k1.Obim();
   k1.Povrsina();
   k1.SetStranica(8, 2);
   k1.Obim();
   k1.Povrsina();
   k1.SetStranica(9);
   k1.Obim();
   k1.Povrsina();
   //pozivaju se metode izvedene klase 
   //sem k.SetStranica(8, 2); tada se poziva
   //metoda bazne klase
   Console.WriteLine();

   Pravougaonik p2 = new Kvadrat(5);
   p2.Obim();
   p2.Povrsina();
   p2.SetStranica(8, 7);
   p2.Obim();
   p2.Povrsina();
   //pozivaju se metode bazne klase
   
   Console.ReadKey();
   }
}

Konstruisanje objekta osnovnog tipa preko konstruktora klase izvedenog tipa ima smisla kada različiti objekti izvedenog tipa potiču iz iste bazne klase i međusobno su veoma slični.

//Primer 1:
SahovskaFigura kralj = new Kralj(“beli”);
SahovskaFigura lovac = new Lovac(“beli”);

//Primer 2:
Osoba m1 = new Moderator();
Osoba n1 = new Nastavnik();
Osoba p1 = new Polaznik();

Višenivovsko nasleđivanje

U ovom slučaju klasa nasleđuje neku drugu klasu koja je već nasledila neku klasu. Klasa jednakostranični trougao je izvedena iz klase jednokraki trougao koji je izveden iz klase trougao. Klasu pravougaonik može da nasledi klasa kvadrat a klasu kvadrat može da nasledi klasa kocka.

class Pravougaonik
{
    protected int a;
    protected int b;

    public Pravougaonik():this(1,1){ }

    public Pravougaonik(int a, int b) 
    {
       Console.WriteLine("Pravljenje pravougaonika");
       this.a = a;
       this.b = b; 
    }

    public void SetStranica(int a, int b)
    {
        this.a = a;
        this.b = b;
        Console.WriteLine("Nove stranice pravougaonika su a:{0} i b:{1}", a,b);
    }

    public virtual void Obim()
    {
         int O =  2*(a + b);
         Console.WriteLine("Obim pravougaonika je:{0}",O);
    }

    public virtual void Povrsina()
    {
          int P = a*b;
          Console.WriteLine("Povrsina pravougaonika je:{0}", P);
    }
}
class Kvadrat:Pravougaonik
{ 
    public Kvadrat()
    {
        Console.WriteLine("Pravljenje kvadrata");
    }

    public Kvadrat(int a) : base(a, a)
    {
         Console.WriteLine("Pravljenje kvadrata");
    }

    public void SetStranica(int a)
    {
         this.a = a;
         Console.WriteLine("Nove stranica kvadrata je a:{0}", a);
    }

    public override void Obim()
    {
          int O = 4*a;
          Console.WriteLine("Obim kvadrata je:{0}", O);
    }

    public override void Povrsina()
    {
          int P = a * a;
          Console.WriteLine("Povrsina kvadrata je:{0}", P);
    }
}
class Kocka : Kvadrat
{
    public Kocka()
    {
        Console.WriteLine("Pravljenje kocke");
    }

    public Kocka(int a) : base(a)
    {
         Console.WriteLine("Pravljenje kocke");
    }

    public new void SetStranica(int a)
    {
          this.a = a;
          Console.WriteLine("Nove stranica kocke je a:{0}", a);
    }

    public override int Povrsina()
    {
          int P = 6*base.Povrsina();
          Console.WriteLine("Povrsina kocke je:{0}", P);
          return P;
    }

    public int Zapremina()
    {
          int V = a* base.Povrsina();
          Console.WriteLine("Zapremina kocke je:{0}", V);
          return V;
     }
}
class Program
{
    static void Main(string[] args)
    {

        Pravougaonik p1 = new Pravougaonik(5, 6);
        p1.Obim();
        p1.Povrsina();
        p1.SetStranica(10, 8);
        p1.Obim();
        p1.Povrsina();

        Console.WriteLine();

        Kvadrat k1 = new Kvadrat(5);
        k1.Obim();
        k1.Povrsina();
        k1.SetStranica(8, 2);
        k1.Obim();
        k1.Povrsina();
        k1.SetStranica(9);
        k1.Obim();
        k1.Povrsina();
        //pozivaju se metode izvedene klase sem 
        //k.SetStranica(8, 2); tada se poziva
        //metoda bazne klase
        Console.WriteLine();
        ...
        ...
        Kocka K = new Kocka(10);
           
        K.Povrsina();
        K.Zapremina();
        K.SetStranica(12, 8);
        K.Povrsina();
        K.Zapremina();

        Console.ReadKey();
    }
}

Ukoliko klasa C nasleđuje klasu B a klasa B nasleđuje klasu A i ako postoji metoda Metod u sve tri klase ako je metoda u klasi B redefinisana a u klasi C nije tada u klasi C postoje dve metode od kojih je metoda iz klase B maskirana. Ako pravimo objekat klase A ili B na osnovu konstruktora klase C tada će za ove objekte biti dostupna redefinisana metoda Metod iz klase B dok će za objekte klase C biti dostupna metoda iz klase C.
Zadaci: 234 i 248

 

APSTRAKTNE KLASE

- Da bi se metoda ili klasa označila kao apstraktna koristi se ključna reč abstract.
- Klasa koja ima bar jednu apstraktnu metodu naziva se apstraktna klasa. Apstraktna klasa ne mora da ima apstraktnu metodu već je samo potrebno da bude definisana pomoću ključne reči abstract.
- Apstraktna metoda je prazna metoda tj. metoda koja nema implementaciju. Apstraktna metoda dakle nema telo, nema ni prazno telo.
- Apstaktna klasa može imati metode koje nisu apstraktne.
- Apstraktna klasa ne može da se instancira. Odnosno nije moguće kreirati objekat apstraktne klase.

APSTRAKTNE KLASE

- Klasa koja je izvedena iz apstraktne klase mora da realizuje (implementira) sve apstraktne metode tj. da definiše njihovo telo korišćenjem ključne reči override.
- Apstraktne metode su već same po sebi i virtualne jer moraju da se redefinišu u nasleđenoj klasi. Kod apstraktnih metoda je poznato šta rade ali ne i kako to rade.
- Abstract i override funkcije moraju imati: isti naziv, isti modifikator pristupa ( protected, public, private ), istu povratnu vrednost ( void, string, int, float, double, itd ...), iste argumente (po broju i tipu).

 

abstract class Figura
{
     abstract public float Obim();
     abstract public float Povrsina();
}
class Pravougaonik:Figura
{
    private float a;
    private float b;

    public Pravougaonik():this(1,1){ }

    public Pravougaonik(float a, float b)
    {
        this.a = a;
        this.b = b;
    }

    public override float Obim()
    {
        return 2*(a+b);
    }

    public override float Povrsina()
    {
        return a*b;
    }
}
class Krug : Figura
{
    private float r;
        
    public Krug(float r)
    {
         this.r = r;
    }

    public override float Obim()
    {
          return 2 * r*(float)Math.PI;
    }

    public override float Povrsina()
    {
         return r * r* (float)Math.PI;
    }
}
static void Main(string[] args)
{

     Figura p = new Pravougaonik(5, 6);

     Console.WriteLine("Obim pravougaonika je:{0} a povrsina je:{1}", p.Obim(), p.Povrsina());

     Figura k = new Krug(5);
     Console.WriteLine("Obim kruga je:{0} a povrsina je:{1}", k.Obim(), k.Povrsina());

     Console.ReadKey();
}

INTERFEJSI

- Interfejs predstavlja "ugovor" kojim se garantuje da će se klasa, koja je nasledila taj interfejs, ponašati na određeni način.
- Interfejs je koncept koji razdvaja specifikaciju metoda od njegove implementacije.
- Klasa može da nasledi tj. implementira više interfejsa.

- Interfejs može da nasledi više interfejsa.

- Struktura takođe može da nasledi interfejs.
- Klasa može da nasledi jednu klasu i pri tome da nasledi jedan ili više interfejsa.

interface Figura
{
    int Obim();
    int Povrsina();
}
class Pravougaonik:Figura
{
     protected int a;
     protected int b;

     public Pravougaonik() : this(1, 1){ }

     public Pravougaonik(int a, int b)
     {
         Console.WriteLine("Pravljenje pravougaonika");
         this.a = a;
         this.b = b;
     }

     public void SetStranica(int a, int b)
     {
         this.a = a;
         this.b = b;
         Console.WriteLine("Nove stranice pravougaonika su a:{0} i b:{1}", a, b);
     }

     public virtual int Obim()
     {
         int O = 2 * (a + b);
         Console.WriteLine("Obim pravougaonika je:{0}", O);
         return O;
     }

     public virtual int Povrsina()
     {
         int P = a * b;
         Console.WriteLine("Povrsina pravougaonika je:{0}", P);
         return P;
     }
}
class Kvadrat : Pravougaonik, Figura
{
    public Kvadrat()
    {
         Console.WriteLine("Pravljenje kvadrata");
    }

    public Kvadrat(int a) : base(a, a)
    {
         Console.WriteLine("Pravljenje kvadrata");
    }

    public void SetStranica(int a)
    {
         this.a = a;
         Console.WriteLine("Nove stranica kvadrata je a:{0}", a);
    }

    public override int Obim()
    {
         int O = 4 * a;
         Console.WriteLine("Obim kvadrata je:{0}", O);
         return O;
    }

    public override int Povrsina()
    {
        int P = a * a;
        Console.WriteLine("Povrsina kvadrata je:{0}", P);
        return P;
     }
}
class Program
{
    static void Main(string[] args)
    {
        Pravougaonik p1 = new Pravougaonik(5, 6);
        p1.Obim();
        p1.Povrsina();
        p1.SetStranica(10, 8);
        p1.Obim();
        p1.Povrsina();

        Console.WriteLine();

        Kvadrat k1 = new Kvadrat(5);
        k1.Obim();
        k1.Povrsina();
        k1.SetStranica(8, 2);
        k1.Obim();
        k1.Povrsina();
        k1.SetStranica(9);
        k1.Obim();
        k1.Povrsina();
        //pozivaju se metode izvedene klase sem k.SetStranica(8, 2); 
        //tada se poziva metoda bazne klase
        Console.WriteLine();

        Console.ReadKey();
     }
}

Polimorfizam u nasleđivanju

By lanik

Polimorfizam u nasleđivanju

  • 508