Template (software)
Een template of een generic (type) is een sjabloon voor een stuk code. Met behulp van templates is het mogelijk een stuk broncode te generaliseren, zodat het voor meer object types bruikbaar is. Templates zijn beschikbaar in de programmeertaal C++, maar sinds enige tijd ook in andere talen, zoals Java en C#. Soms worden templates ook wel aangeduid met de term 'generics'.
Templates kunnen gebruikt worden met functies en met klasses. Veel talen gebruiken ze bij container-klassen, die door gebruik van templates 'type-safe' worden.
Inhoud |
[bewerk] Voorbeeld Generieke Functie
Een voorbeeld is het bepalen van de kleinste van twee objecten. In plaats van aparte functies voor int, float en double, maar ook voor std::string, of andere zelf te schrijven objecten kan een template functie gebruikt worden:
template <typename T> T kleinste(T a, T b) { if (a < b) return a; return b; }
Deze functie kan vervolgens voor alle klasses gebruikt worden die '<' ondersteunen. Dit is een belangrijk verschil met de 'traditionele' manier van programmeren in OO-talen: normaalgesproken staat vast waaraan de parameters van een functie moeten voldoen (in een interface of een type-specificatie). Een functie kan bijvoorbeeld aangeven dat het alleen objecten wil hebben die een interface X implementeert waarin een methode Y voorkomt. Met templates wordt dit niet van tevoren afgedwongen, maar wordt er pas gekekeken of een bepaald type in een template 'past' als deze ook daadwerkelijk wordt gebruikt.
[bewerk] Voorbeeld Klasse Met Template
Hier is een voorbeeld van een lijst waaraan items kunnen worden toegevoegd, en waarvan de elementen met de index operator kunnen worden benaderd. In feite is dit een uitgeklede container.
template<typename T> class Lijst { public: Lijst():m_Laatste(0),m_Lijst(NULL) {} virtual ~Lijst() {delete[] m_Lijst;} void VoegToe(const T &item) { T* NieuweLijst = new T[m_Laatste + 1]; for (int i = 0; i < m_Laatste; i++) { NieuweLijst[i] = m_Lijst[i]; } NieuweLijst[m_Laatste] = item; delete [] m_Lijst; m_Lijst = NieuweLijst; m_Laatste++; } int Afmetingen() {return m_Laatste;} operator [](int index) {return m_Lijst[index]}; protected: T* m_Lijst; int m_Laatste; };
[bewerk] Template Metaprogramming
Templates kunnen ook worden gebruikt om 'compile-time' (dus niet wanneer het programma wordt uitgevoerd, maar wanneer het wordt gecompileerd) berekeningen en andere 'trucs' uit te halen. Het beroemdste voorbeeld van Template metaprogramming in C++ is:
template<int N> class Factorial { public: enum { value = N * Factorial<N-1>::value }; }; class Factorial<1> { public: enum { value = 1 }; }; int faculteitVan20 = Factorial<20>::value;
In bovenstaand voorbeeld wordt faculteitVan20 gedefinieerd als de waarde van Factorial<20>::value, die op zijn beurt weer is gedefinieerd als Factorial<19>::value * 20. Dit gaat zo door, tot Factorial<1>, die standaard is gedefinieerd als 1. In dit voorbeeld wordt er gebruikgemaakt van recursie, maar er zijn technieken bedacht om ook programmeerconcepten als If/Else en For te kunnen gebruiken bij Template Metaprogramming.
[bewerk] Generic Types in C#
Generic Types kunnen in C# 2.0 gebruikt worden om type-safe met collecties te kunnen werken. In onderstaand voorbeeld kan aan de niet-generieke collectie Arraylist elk type object worden toegevoegd maar aan de generieke collectie List<A> alleen objecten van type A. De generieke collectie List<A> is daarom type-safe.
class A { } class B { } private void TestLijsten() { ArrayList lijst = new ArrayList(); lijst.Add(new A()); lijst.Add(new B()); List<A> lijstA = new List<A>(); lijstA.Add(new A()); //lijstA.Add(new B()); compileert niet! }