U nastavku su iza dugmića sakrivena objačnjenja nekih pojmova, koji su objašnjeni na najjednostavniji način, za ponavljanje:

Zamislite da pravimo nešto u fabrici, na primer, igračku. Da bismo napravili više istih igračaka, prvo nam treba šablon ili plan po kojem ćemo praviti te igračke. Taj šablon je kao klasa u programiranju.

Klasa

U C#, klasa je kao taj šablon ili plan koji opisuje kako nešto izgleda i šta može da radi. U njoj možemo opisati stvari kao što su osobine (kao boja ili veličina) i ponašanja (kao skakanje ili hodanje).

Objekat

Kad imamo klasu (šablon), možemo napraviti objekat, odnosno stvarni primerak tog šablona. Na primer, ako imamo klasu koja opisuje Igračku, možemo napraviti mnogo igračaka koristeći taj isti plan.

Zamislite da pravimo program koji radi sa automobilima. Možemo napraviti klasu "Automobil", koja će opisivati kako automobil izgleda (npr. boja, model) i šta može da radi (npr. vozi, trubi). Kada napišemo klasu, možemo napraviti više objekata (konkretnih automobila) koristeći taj plan.

Primer kako to izgleda u C# kodu:
// Definisanje klase (šablona)
class Automobil
{
    public string Boja;
    public string Model;

    public void Vozi()
    {
        Console.WriteLine("Automobil vozi.");
    }

    public void Trubi()
    {
        Console.WriteLine("Automobil trubi.");
    }
}

// Pravljenje objekata (stvarnih automobila)
Automobil auto1 = new Automobil();
auto1.Boja = "Crvena";
auto1.Model = "BMW";

Automobil auto2 = new Automobil();
auto2.Boja = "Plava";
auto2.Model = "Audi";

auto1.Vozi();  // Ispisuje "Automobil vozi."
auto2.Trubi(); // Ispisuje "Automobil trubi."
      

Šta se ovde događa?

  • Klasa "Automobil" je naš plan. Ona ima osobine (boja, model) i ponašanja (vozi, trubi).
  • auto1 i auto2 su objekti napravljeni na osnovu tog plana. Oni su stvarni primerci automobila koji imaju različite boje i modele.
  • Svaki objekat može koristiti ponašanja definisana u klasi, kao što je vožnja ili trubljenje.

Dakle, klasa je kao šablon, a objekat je stvarni primerak tog šablona koji koristimo u programu.

Konstruktor u C# možemo zamisliti kao specijalan metod koji se koristi za pravljenje ili "konstrukciju" objekata.

Zamislite da smo u radionici i pravimo robota. Kada napravimo robota, odmah moramo da mu dodelimo određene osobine – na primer, koje će boje biti i koliko će dugih ruku imati. Konstruktor je kao osoba koja, u trenutku pravljenja robota, postavi sve te osobine kako treba.

Šta je konstruktor?

  • Konstruktor je metod koji se automatski poziva kad god napravimo novi objekat iz klase.
  • On služi da inicijalizuje (postavi) početne vrednosti za osobine objekta.

Kako izgleda konstruktor?

Konstruktor se zove isto kao i klasa, i nema povratnu vrednost (npr. ne pišemo void ili int ispred njega).

Primer u C#:

class Automobil
{
    public string Boja;
    public string Model;

    // Konstruktor
    public Automobil(string boja, string model)
    {
        Boja = boja;
        Model = model;
    }

    public void Vozi()
    {
        Console.WriteLine("Automobil vozi.");
    }
}

class Program
{
    static void Main()
    {
        // Koristimo konstruktor da napravimo novi objekat i odmah mu postavimo osobine
        Automobil auto1 = new Automobil("Crvena", "BMW");
        Automobil auto2 = new Automobil("Plava", "Audi");

        Console.WriteLine("Auto1: " + auto1.Boja + ", " + auto1.Model);  // Ispisuje: Auto1: Crvena, BMW
        Console.WriteLine("Auto2: " + auto2.Boja + ", " + auto2.Model);  // Ispisuje: Auto2: Plava, Audi
    }
}

Šta se ovde događa?

  • Kada napravimo novi Automobil pomoću konstruktora (npr. new Automobil("Crvena", "BMW")), konstruktor automatski postavlja boju i model automobila.
  • Konstruktor ima dva parametra – boja i model. Kada pravimo automobil, mi odmah kažemo koje vrednosti želimo da ti parametri imaju (npr. "Crvena" i "BMW").
  • Nakon što se automobil napravi, odmah ima postavljene osobine koje smo mu zadali.

Zašto je konstruktor važan?

Konstruktor nam pomaže da u trenutku pravljenja objekta postavimo sve što je potrebno, umesto da naknadno ručno dodeljujemo vrednosti. To olakšava rad i čini kod urednijim.

Metode su kao male funkcije ili zadaci koje program može da izvrši. One pomažu programeru da organizuje kod tako da se neki zadatak izvrši na jednom mestu, a ne da se piše isti kod više puta.

Metode unutar klasa

U C#, metode se često nalaze unutar klasa. Klase su kao nacrti za stvaranje objekata, a metode u njima definišu ponašanje tih objekata.

Evo kako bi izgledala jednostavna klasa sa metodom:

class Auto
{
    // Ova metoda će opisati zvuk koji pravi auto
    public void UpaliAuto()
    {
        Console.WriteLine("Auto je upaljen!");
    }
}

U ovom primeru imamo klasu Auto, a unutar nje metodu UpaliAuto. Ova metoda, kada je pozvana, samo ispiše poruku "Auto je upaljen!". Metoda se koristi tako da se prvo napravi objekat tipa Auto, a zatim se pozove metoda na tom objektu

Auto mojAuto = new Auto();
mojAuto.UpaliAuto();

Kada pozovemo UpaliAuto(), program će ispisati poruku.

Metode van klasa

U C#, svaki kod mora biti deo neke klase ili strukture, pa metode van klasa u tradicionalnom smislu ne postoje. Međutim, moguće je koristiti statističke (static) metode unutar klasa, koje mogu da se pozivaju bez kreiranja objekta.

Evo primera statičke metode:

class Kalkulator
{
    public static int Saberi(int a, int b)
    {
        return a + b;
    }
}

Ova metoda Saberi je statička i sabira dva broja. Pošto je statička, ne moramo da kreiramo objekat klase Kalkulator da bismo je koristili:

int rezultat = Kalkulator.Saberi(3, 5);
Console.WriteLine(rezultat); // Ispisuje 8

Ukratko:

  • Metode u klasama: definiraju zadatke koje objekti te klase mogu da izvrše.
  • Statičke metode: mogu da se koriste bez kreiranja objekta i obično obavljaju funkcije vezane za celu klasu, a ne za pojedinačne objekte.

Metode pomažu da organizujemo i ponovo koristimo kod na jednostavan način, umesto da stalno pišemo iste delove programa iznova.

Nasleđivanje klasa u C# možete zamisliti kao "porodično nasleđivanje", ali u svetu programiranja.

Zamislte da pravimo programe i u njima pravimo "klase". Klasa je kao šablon ili plan za pravljenje objekata. Na primer, klasa "Životinja" može imati osobine kao što su ime, boja, i ponašanja kao što su hodanje i disanje.

Sada, ako želimo da napravimo klasu "Pas", ne moramo sve to ponovo da pišemo. Umesto toga, klasa "Pas" može naslediti sve osobine i ponašanja iz klase "Životinja", jer je pas vrsta životinje. Klasa "Pas" dobija sve što klasa "Životinja" ima, ali može dodati i neke svoje specifične osobine, kao što su lajanje.

Kako to izgleda u kodu?
// Osnovna klasa
class Zivotinja
{
    public string Ime;
    public string Boja;

    public void Hodaj()
    {
        Console.WriteLine("Životinja hoda.");
    }
}

// Izvedena klasa
class Pas : Zivotinja
{
    public void Laj()
    {
        Console.WriteLine("Pas laje.");
    }
}

  • Klasa "Zivotinja" je osnovna klasa koja ima ime, boju i može hodati.
  • Klasa "Pas" nasleđuje klasu "Zivotinja". To znači da pas može imati ime, boju i hodati, ali pas može i lajati jer ima svoju specifičnu metodu Laj().

Dakle, nasleđivanje nam pomaže da ne pišemo iste stvari iznova i iznova, već da koristimo ono što smo već napisali i nadograđujemo ga.

Kada se radi o nasleđivanju klasa u C#, konstruktori osnovne klase i izvedene klase imaju specifičan način na koji rade zajedno. Evo kako to funkcioniše:

Osnovna pravila nasleđivanja i konstruktora

  1. Konstruktor osnovne klase se ne nasleđuje automatski. Iako izvedena klasa nasleđuje osobine (polja) i metode osnovne klase, konstruktori osnovne klase se ne nasleđuju direktno.
  2. Konstruktor izvedene klase mora pozvati konstruktor osnovne klase. Kada pravimo objekat izvedene klase, prvo se poziva konstruktor osnovne klase, a zatim konstruktor izvedene klase.

Kako pozvati konstruktor osnovne klase?

Kada izvedena klasa ima svoj konstruktor, korisi se ključna reč base da bi se eksplicitno pozvao konstruktor osnovne klase i prosledili potrebni parametri.

Primer sa objašnjenjem:

Zamislite da imamo osnovnu klasu "Zivotinja" i izvedenu klasu "Pas". Svaka od njih ima svoj konstruktor.

// Osnovna klasa
class Zivotinja
{
    public string Ime;

    // Konstruktor osnovne klase
    public Zivotinja(string ime)
    {
        Ime = ime;
        Console.WriteLine("Konstruktor Zivotinja: Ime je " + ime);
    }
}

// Izvedena klasa
class Pas : Zivotinja
{
    public string Rasa;

    // Konstruktor izvedene klase
    public Pas(string ime, string rasa) : base(ime)  // Poziv konstruktora osnovne klase
    {
        Rasa = rasa;
        Console.WriteLine("Konstruktor Pas: Rasa je " + rasa);
    }
}

class Program
{
    static void Main()
    {
        // Pravljenje objekta izvedene klase
        Pas pas = new Pas("Rex", "Labrador");
    }
}

Šta se ovde događa?

  1. Osnovna klasa "Zivotinja" ima konstruktor koji zahteva parametar ime.
  2. Izvedena klasa "Pas" ima konstruktor koji zahteva dva parametra: ime i rasa.
  3. Kada pravimo novi objekat "Pas", prvo se poziva konstruktor osnovne klase "Zivotinja" preko ključne reči base, a zatim se nastavlja izvršavanje konstruktora klase "Pas".
  4. base(ime) je način na koji pozivamo konstruktor osnovne klase i prosleđujemo mu parametar ime.

Ispis:

Konstruktor Zivotinja: Ime je Rex
Konstruktor Pas: Rasa je Labrador

Zašto se konstruktor osnovne klase poziva?

Razlog za to je što osnovna klasa može imati određene osobine koje moraju biti inicijalizovane, a konstruktor je mesto gde se to radi. Da bi objekat izvedene klase (u ovom slučaju Pas) bio kompletan, moramo prvo da postavimo sve što pripada osnovnoj klasi (kao što je Ime u klasi "Zivotinja").

Šta ako ne pozovemo konstruktor osnovne klase?

Ako osnovna klasa ima konstruktor koji zahteva parametre, moramo ga eksplicitno pozvati iz izvedene klase. Ako ne napišemo base, kompajler će prijaviti grešku. Međutim, ako osnovna klasa ima prazan (default) konstruktor, on će se automatski pozvati čak i ako ga eksplicitno ne napišemo.

Zaključak

Kada koristimo nasleđivanje, konstruktori osnovne i izvedene klase rade zajedno. Prvo se poziva konstruktor osnovne klase (koji može postaviti osnovne osobine), a zatim se izvršava konstruktor izvedene klase (koji može dodati specifične osobine). Korišćenje ključne reči base omogućava nam da prosledimo vrednosti konstruktoru osnovne klase.


Nasleđivanje je ključni koncept objektno orijentisanog programiranja koji omogućava kreiranje novih klasa koje nasleđuju osobine i metode iz postojećih klasa. U C#, moguće je kreirati generičke klase koje nasleđuju druge generičke klase, čime se dodatno povećava fleksibilnost i ponovna upotrebljivost koda.

Ključni pojmovi:
  • Generička klasa: Klasa koja koristi generičke tipove kao parametre, što joj omogućava da radi sa različitim tipovima podataka.
  • Izvedena klasa: Klasa koja nasleđuje osobine i metode iz druge klase, tzv. osnovne ili bazne klase.
  • Generička izvedena klasa: Generička klasa koja nasleđuje drugu generičku klasu, pri čemu može zadržati ili promeniti generičke tipove.
Sintaksa za kreiranje izvedene generičke klase:

 
public class BaseClass<T>
{
public T Value { get; set; }

public BaseClass(T value)
{
Value = value;
}
}

public class DerivedClass<T> : BaseClass<T>
{
public string Description { get; set; }

public DerivedClass(T value, string description) : base(value)
{
Description = description;
}
}

  • DerivedClass<T> je izvedena generička klasa koja nasleđuje generičku klasu BaseClass<T>.
Primer upotrebe izvedene generičke klase:

class Program
{
static void Main(string[] args)
{
DerivedClass<int> derived = new DerivedClass<int>(10, "This is an integer");
Console.WriteLine("Value: "+ derived.Value + ", Description: " + derived.Description);

DerivedClass<string> derivedString = new DerivedClass<string>("Hello", "This is a string");
Console.WriteLine("Value: " + derivedString.Value + ", Description: " + derivedString.Description);
}
}

U ovom primeru, izvedena klasa DerivedClass<T> nasleđuje osobine i metode iz klase BaseClass<T>, ali dodaje i novu osobinu Description.

Nasleđivanje sa više generičkih tipova:

Možete kreirati izvedenu klasu koja koristi različite generičke tipove od svoje osnovne klase:

public class Pair<T1, T2>
{
public T1 First { get; set; }
public T2 Second { get; set; }

public Pair(T1 first, T2 second)
{
First = first;
Second = second;
}
}

public class ExtendedPair<T1, T2, T3> : Pair<T1, T2>
{
public T3 Third { get; set; }

public ExtendedPair(T1 first, T2 second, T3 third) : base(first, second)
{
Third = third;
}
}

U ovom primeru, klasa ExtendedPair<T1, T2, T3> nasleđuje klasu Pair<T1, T2> i dodaje treći generički tip T3.

Dodatni zadatak (u cilju ponavljanja gradiva) :  U poslednje kreiranoj klasi kreirati metodu Ispis kojom se ispisuju sva tri elementa .

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication8
{
public class BaseClass<T>
{
public T Value { get; set; }

public BaseClass(T value)
{
Value = value;
}
}

public class DerivedClass<T> : BaseClass<T>
{
public string Description { get; set; }

public DerivedClass(T value, string description)
: base(value)
{
Description = description;
}
}
public class Pair<T1, T2>
{
public T1 First { get; set; }
public T2 Second { get; set; }

public Pair(T1 first, T2 second)
{
First = first;
Second = second;
}
}

public class ExtendedPair<T1, T2, T3> : Pair<T1, T2>
{
public T3 Third { get; set; }

public ExtendedPair(T1 first, T2 second, T3 third)
: base(first, second)
{
Third = third;
}
public void ispis()
{
Console.WriteLine(this.First + " " + this.Second+ " " + this.Third);
}
}
class Program
{
static void Main(string[] args)
{
DerivedClass<int> derived = new DerivedClass<int>(10, "This is an integer");
Console.WriteLine("Value: " + derived.Value + ", Description: " + derived.Description);

DerivedClass<string> derivedString = new DerivedClass<string>("Hello", "This is a string");
Console.WriteLine("Value: " + derivedString.Value + ", Description: " + derivedString.Description);

Console.WriteLine("Primer 2:");

Pair<int, string> parovi1 = new Pair<int, string>(1, "abrakadabra");
Pair<char, int> par2 = new Pair<char, int>('a',10);
ExtendedPair<int, string, string> par3x = new ExtendedPair<int, string, string>(1, "Pera","Ždera");

Console.WriteLine("Prvi par: " + parovi1.First + " , " + parovi1.Second);
Console.WriteLine("Drugi par: " + par2.First + " , " + par2.Second);
Console.WriteLine("Treći X par: " + par3x.First + " , " + par3x.Second + " , " + par3x.Third);
Console.WriteLine(); // jedan prazan red
par3x.ispis();
}
}
}

Prednosti korišćenja izvedenih generičkih klasa:
  • Ponovna upotrebljivost koda: Izvedene generičke klase mogu koristiti logiku iz osnovnih klasa, a da pri tom dodaju nove funkcionalnosti.
  • Fleksibilnost: Omogućava kreiranje specifičnih implementacija bez potrebe za ponavljanjem koda.
  • Sigurnost tipova: Nasleđivanje generičkih klasa omogućava rad sa različitim tipovima podataka uz proveru tipova tokom kompajliranja.
Zadaci za učenike:
  1. Kreiranje generičke izvedene klase: Kreirati klasu Triple<T1, T2, T3> koja nasleđuje klasu Pair<T1, T2> i dodaje još jednu vrednost tipa T3.
  2. Nasleđivanje sa ograničenjima: Kreirati klasu koja nasleđuje generičku klasu Pair<T1, T2> sa ograničenjima (npr. gde generički tip mora biti string ili broj).

  1. Koje su prednosti korišćenja izvedenih generičkih klasa u odnosu na obične generičke klase?
  2. Kako biste implementirali ograničenja na generički tip u izvedenoj klasi?
  3. Kada bi bilo korisno koristiti nasleđivanje sa više generičkih tipova?

Last modified: Tuesday, 2 December 2025, 4:55 AM