Generičko programiranje (eng. Generic programming) je stil računalnog programiranja u kojem su algoritmi pisani na način da predstavljaju "kostur" koji je implementiran tek kasnije, kada se odrede argumenti. Ovaj pristup, koji je ML osnovao 1973. godine, omogućuje pisanje zajedničkih funkcija ili klasa koje se razlikuju samo u vrsti argumenta na kojima djeluju kada se koriste, čime se smanjuje dupliciranje.
Takvi softverski elementi poznati su kao generički podaci (eng. generics) u programskim jezicima Python, Ada, C #, Delphi, Eiffel, F #, Java, Rust, Swift, TypeScript i Visual Basic .NET.
Jezična podrška generičkog programiranja
Generičko programiranje na neki način je postojalo barem od 1970-ih u jezicima kao što su ML, CLU i Ada, a kasnije su ih usvojili mnogi objektni i objektno orijentirani jezici, uključujući BETA, C ++, D, Eiffel, Java.
U objektno orijentiranim jezicima
Prilikom stvaranja klasa spremnika u statički pisanim jezicima, nije zgodno pisati posebne implementacije za svaku vrstu podataka, posebno ako je kôd za svaku vrstu podataka gotovo identičan. Ovakvo preopterećivanje parametara funkcije naziva se ad-hoc polimorfizam. Na primjer, u C ++, umjesto pisanja "zbroji" funkcije za svaki korišteni tip podatka, pomoću generičkog programiranja na sljedeći način možemo izbjeći pisanje viša koda:
int zbroji (int a, int b)
{
return a + b;
}
double zbroji (double a, double b)
{
return a + b;
}
// "Razlomak" predstavlja korisnički izrađenu klasu koja ima implementiran operator+
Razlomak zbroji (Razlomak a, Razlomak b)
{
return a + b;
}
/*------------------- KORISTEĆI GENERIČKO PROGRAMIRANJE POSTAJE: -------------------*/
template<typename Tip>
Tip zbroji (Tip a, Tip b)
{
return a + b;
}
// Funkcija će raditi sve dok podatak tipa "Tip" ima implementiran operator +
// Dakle, to su svi primitivni tipovi te korisnički kreirani tipovi kojima su eksplicitno
// izrađene operator+ metode
// Primjer poziva funkcije sa predloškom
int main()
{
std::cout << "Zbroj: " << zbroji(3, 4) << "\n"; // implicitni poziv; compiler zaključuje da je "Tip" = int
std::cout << "Zbroj: " << zbroji<double>(3.0, 4.0) << "\n"; // eksplicitni poziv; 3.0 i 4.0 su double
class Igrac
{
public:
int zdravlje;
Igrac() : zdravlje(10) {}
Igrac(int novoZdravlje) : zdravlje(novoZdravlje) {}
Igrac operator+(Igrac drugiIgrac)
{
return zdravlje + drugiIgrac.zdravlje;
}
} a, b;
Igrac c = zbroji(a, b);
/*
- Kreiraju se klase koje sadržavaju primitivni podatak tipa integer "zdravlje", poziva se konstruktor "Igrac()"
koji postavlja varijablu "zdravlje" na vrijednost 10
- Compiler kreira funkciju "Igrac zbroji(Igrac a, Igrac b)" na temelju kreirane metode "operator+"
- Operator+ zbraja dva igraca tako da zbroji njihove varijable "zdravlje" (10 + 10 = 20)
- U funkciji "zbroji" kreira se novi "Igrac" pozivom konstruktora "Igrac(int novoZdravlje)", gdje je argument "20"
*/
std::cout << "Zdravlje igraca: " << c.zdravlje << "\n";
return 0;
}
Predlošci u C++
C++ koristi predloške za omogućavanje generičkih tehnika programiranja. Standardna knjižnica C ++ uključuje Standard Template Library ili STL koja pruža okvir predložaka za zajedničke strukture podataka i algoritme. Predlošci u C ++ mogu se koristiti i za metaprogramiranje predložaka, što je način prethodne procjene dijela koda u vrijeme kompajliranja, a ne u vremenu izvođenja.
Tehnički pregled
Postoje dvije vrste predložaka: predlošci funkcijâ i predlošci klasâ. Predložak funkcije je obrazac za stvaranje uobičajenih funkcija na temelju parametara koji se pošalju kada se funkcija kreira. Na primjer, C++ biblioteka standardnih predložaka sadrži predložak funkcije max(x, y) koji stvara funkcije koje vraćaju ili x ili y, ovisno o tome koji je veći. max()
može se definirati ovako:
template <typename T>
T max(T x, T y) {
return x < y ? y : x;
}