A generikus programozás a számítógépes programozás egy olyan stílusa, amelyben az algoritmusok a később meghatározandó típusok formájában írják fel, amelyeket aztán szükség esetén megadnak a a paraméterként megadott típusokhoz. Ezt a megközelítést az ML programozási nyelv vezette be 1973-ban,Milner, R.; Morris, L.; Newey, M. (1975). "A Logic for Computable Functions with Reflexive and Polymorphic Types". Proceedings of the Conference on Proving and Improving Programs. lehetővé teszi olyan közös függvények vagy típusok írását, amelyek csak abban a típusban különböznek egymástól, amelyen működnek, így csökkentve a párhuzamosságot. Az ilyen szoftverek entitások néven generikus Ada, C #, Delphi, Eiffel, F #, Java, Nim, Python, Rust, Swift, TypeScript és a Visual Basic .NET. Paraméteres polimorfizmusként ismerik őket az ML-ben, Scalában, Juliában és Haskellben (a Haskell-közösség a "generikus" kifejezést is használja egy kapcsolódó, de némileg eltérő fogalomra); sablonok C++ és D nyelven; és paraméterezett típusok a nagy hatású 1994-es Design PatternsGamma, Erich; Helm, Richard; Johnson, Ralph; Vlissides, John (1994). Design Patterns. Addison-Wesley. ISBN 0-201-63361-2. című könyvben.

A "generikus programozás" kifejezést eredetileg David Musser és Alexander Stepanov találta ki a fentieknél specifikusabban, egy olyan programozási paradigma leírására, amelyben a típusokra vonatkozó alapvető követelményeket elvonták az algoritmusok és adatstruktúrák konkrét példáitól, és formalizálták mint fogalmak, általános funkciókkal, amelyek e fogalmak szempontjából valósulnak meg, jellemzően a fent leírt nyelvi genericitási mechanizmusokat alkalmazva.

Stepanov–Musser és más generikus programozási paradigmák Az általános programozást Musser & Stepanov (1989) a következőképpen határozza meg:

A "generikus programozás" paradigma a szoftverbontás megközelítése, amelynek során a típusokra vonatkozó alapvető követelményeket az algoritmusok és az adatstruktúrák konkrét példáiból elvonják és fogalommá formálják, analóg módon az algebrai elméletek absztrakt algebrai absztrakciójával. Ennek a programozási megközelítésnek a korai példáit a Scheme és az Ada hajtották végre, bár a legismertebb példa a Standard Template Library (STL), amely kifejlesztette az iterátorok elméletét, amelyet a szekvencia adatstruktúrák és az azokon működő algoritmusok leválasztására használnak.

Például adott N szekvencia adatstruktúra, pl. egyenként összekapcsolt lista, vektor stb. és M algoritmusok a működésükhöz megkeresés, rendezés stb., közvetlen megközelítéssel minden algoritmust konkrétan az egyes adatstruktúrákra valósítanának meg, N × M kombinációkat adva a megvalósításhoz. A generikus programozási megközelítésben azonban az egyes adatstruktúrák egy iterátor koncepció modelljét adják vissza (egyszerű értéktípus, amelyre le lehet vonni az aktuális érték lekérésére, vagy megváltoztatható, hogy a sorozat másik értékére mutasson), és minden algoritmust megírnak általában az ilyen iterátorok érveivel, pl egy iterátor pár, amely a feldolgozásra kerülő rész vagy tartomány kezdetére és végére mutat. Így csak N + M adatstruktúra-algoritmus kombinációkra van szükség. Az STL több iterátor fogalmat határoz meg, amelyek mindegyike egy szűkebb fogalom finomítását pl. az előremenő iterátorok csak a következő értékre biztosítanak mozgást egy szekvenciában (pl. alkalmasak külön-külön összekapcsolt listához vagy bemeneti adatfolyamhoz), míg a véletlen hozzáférésű iterátor közvetlen állandó idejű hozzáférést biztosít a szekvencia bármely eleméhez (például vektorhoz). Fontos szempont, hogy egy adatstruktúra a legáltalánosabb, hatékonyan megvalósítható koncepció modelljét adja vissza - a számítási bonyolultsági követelmények kifejezetten a fogalommeghatározás részét képezik. Ez korlátozza azokat az adatstruktúrákat, amelyekre egy adott algoritmus alkalmazható, és az ilyen bonyolultsági követelmények döntően meghatározzák az adatstruktúra választását. Az generikus programozást hasonlóan alkalmazták más területeken is, pl. gráfalgoritmusokban.

Megjegyezzük, hogy bár ez a megközelítés gyakran használja a fordítási idő genericitásának / sablonjainak nyelvi jellemzőit, valójában független bizonyos nyelv-technikai részletektől. Alekszandr Sztepanov, a programozás úttörője írta:

Bjarne Stroustrup megjegyezte,

Egyéb programozási paradigmák, amelyeket generikus programozásnak neveznek, magukban foglalják a Datatype generikus programozást, a "Generic Programming – an Introduction" részben leírtak szerint. A Scrap your boilerplate megközelítés egy könnyű, általános programozási megközelítés a Haskell számára.

Ebben a cikkben megkülönböztetjük a fenti általános programozás magas szintű programozási paradigmáit az azok végrehajtásához használt alacsonyabb szintű programozási nyelv genericitási mechanizmusaitól(lásd: Programozási nyelv támogatása az általánossághoz ). Az általános programozási paradigmák további tárgyalásához és összehasonlításához lásd.

Programozási nyelv támogatása általánosságban Az általános szolgáltatások magas szintű nyelvekben legalább az 1970-es évek óta léteznek olyan nyelveken, mint az ML, CLU és Ada, és ezt követően számos objektumalapú és objektumorientált nyelv átvette őket, köztük a BETA, C++, D, Eiffel, Java, és a DEC mára megszűnt Trellis-Owl nyelve.

A genericitást a különböző programozási nyelvek különbözőképpen valósítják meg és támogatják; a "generikus" kifejezést másképp használták a különféle programozási összefüggésekben is. Például a Forthban a fordító lefordíthat kódot fordítás közben, és új fordítói kulcsszavakat és megvalósításokat hozhat létre ezekhez a szavakhoz menet közben. Kevés olyan szó van, amely kiteszi a fordító viselkedését, ezért természetesen olyan genericitást kínál, amelyre azonban a legtöbb Forth szöveg nem hivatkozik. Hasonlóképpen, a dinamikusan tipizált nyelvek, különösen az értelmezett nyelvek, alapértelmezés szerint általában genericitást kínálnak, mivel az értékek átadása a funkcióknak és az értékadás hozzárendelésük típus-közömbös, és ezt a viselkedést gyakran használják absztrakció vagy kód szűkszavúsága szempontjából, azonban ez általában nem címkézett általános, a nyelv által alkalmazott dinamikus gépelési rendszer közvetlen következménye. A kifejezést a funkcionális programozásban használták, különösen a Haskell-szerű nyelvekben, amelyek olyan szerkezeti típusú rendszert használnak, ahol a típusok mindig paraméteresek, és az adott típusok tényleges kódja általános. Ezek a felhasználások továbbra is a kódmentés és az absztrakció renderelésének hasonló célját szolgálják.

A tömbök és a struktúrák előre definiált általános típusokként tekinthetők. A tömb vagy a struktúra minden használata egy új konkrét típust eredményez, vagy újból felhasznál egy korábbi példányt. A tömb és a struktúra elemtípusok paraméterezett típusok, amelyek a megfelelő általános típus példázására szolgálnak. Mindez általában beépül a fordítóba, és a szintaxis eltér a többi általános konstrukciótól. Néhány kibővíthető programozási nyelv megpróbálja egységesíteni a beépített és a felhasználó által meghatározott általános típusokat.

A programozási nyelvek genericitási mechanizmusainak átfogó felmérése következik. Egy specifikus felméréshez, amely összehasonlítja a mechanizmusok alkalmasságát az általános programozásra.

Objektumorientált nyelvekben Ha a konténerosztályokat statikusan tipizált nyelveken hozza létre, kényelmetlen konkrét megvalósításokat írni az egyes tartalmazott adattípusokhoz, különösen, ha az egyes adattípusok kódja gyakorlatilag megegyezik. Például a C++ nyelven a kód duplikációja megkerülhető egy osztálysablon meghatározásával:template<typename T> class List { // Class contents.

List<Animal> list_of_animals; List<Car> list_of_cars;Fent a T helyőrzője annak a típusnak, amelyet a lista létrehozásakor megadnak. Ezek a "T-típusú konténerek", amelyeket sablonoknak hívnak, lehetővé teszik egy osztály újra felhasználását különböző adattípusokkal, mindaddig, amíg bizonyos szerződéseket, például altípusokat és aláírást megtartanak. Ezt az általános jellegű mechanizmust nem szabad összetéveszteni az inklúziós polimorfizmussal, amely a cserélhető alosztályok algoritmikus használata: például egy Moving_Object típusú objektumok listája, amelyek Animal és Car típusú objektumokat tartalmaznak. A sablonok típusfüggetlen funkciókhoz is használhatók, mint az alábbi Swap példában:// "&" denotes a reference template<typename T> void Swap(T& a, T& b) { // A similar, but safer and potentially faster function // is defined in the standard library header <utility> T temp = b; b = a; a = temp; }

std::string world = "World!"; std::string hello = "Hello, "; Swap(world, hello); std::cout << world << hello << ‘\n’; // Output is "Hello, World!".A fent használt C ++ sablonkonstrukciót széles körben idézik , mint azon generikus konstrukciót, amely népszerűsítette a fogalmat a programozók és nyelvtervezők körében, és számos általános programozási idiómát támogat. A D programozási nyelv a C ++ precedensen alapuló, de egyszerűsített szintaxissal teljesen generikus képes sablonokat is kínál. A Java programozási nyelv a J2SE 5.0 bevezetése óta szintaktikailag a C++-on alapuló generikus lehetőségeket kínál.

A C# 2.0, az Oxygene 1.5 (más néven Chrome) és a Visual Basic .NET 2005 olyan konstrukciókkal rendelkezik, amelyek kihasználják a Microsoft .NET-keretrendszerben a 2.0-s verzió óta meglévő generikumok támogatását.

Generikus Adában Az Adának már azóta is vannak generikus termékei, amióta 1977–1980-ig tervezték. A szabványos könyvtár általános szolgáltatásokat használ számos szolgáltatás nyújtásához. Az Ada 2005 egy átfogó, általános tároló könyvtárat egészít ki a standard könyvtárban, amelyet a C++ szabványos sablonkönyvtár ihletett.

Az általános egység olyan csomag vagy alprogram, amely egy vagy több általános formális paramétert vesz fel.

Egy általános formális paraméter egy érték, egy változó, egy konstans, egy típus, egy alprogram, vagy akár egy másik kijelölt generikus egység példánya. Általános formális típusok esetében a szintaxis különbséget tesz diszkrét, lebegőpontos, fixpontos, hozzáférési (mutató) típusok stb. Között. Egyes formális paraméterek alapértelmezett értékekkel rendelkezhetnek.

Egy általános egység példányosításához a programozó átadja az egyes formálisok tényleges paramétereit. Az általános példány ekkor ugyanúgy viselkedik, mint bármely más egység. Lehetséges generikus egységek futás közbeni példányosítása, például egy hurok belsejében.

Példa Az általános csomag specifikációja: generic Max_Size : Natural; -- a generic formal value type Element_Type is private; -- a generic formal type; accepts any nonlimited type package Stacks is type Size_Type is range 0 .. Max_Size; type Stack is limited private; procedure Create (S : out Stack; Initial_Size : in Size_Type := Max_Size); procedure Push (Into : in out Stack; Element : in Element_Type); procedure Pop (From : in out Stack; Element : out Element_Type); Overflow : exception; Underflow : exception; private subtype Index_Type is Size_Type range 1 .. Max_Size; type Vector is array (Index_Type range <>) of Element_Type; type Stack (Allocated_Size : Size_Type := 0) is record Top : Index_Type; Storage : Vector (1 .. Allocated_Size); end record; end Stacks;A generic csomag azonnali végrehajtása: type Bookmark_Type is new Natural; -- records a location in the text document we are editing

package Bookmark_Stacks is new Stacks (Max_Size => 20, Element_Type => Bookmark_Type); -- Allows the user to jump between recorded locations in a documentGeneric csomag példányának használata: type Document_Type is record Contents : Ada.Strings.Unbounded.Unbounded_String; Bookmarks : Bookmark_Stacks.Stack; end record;

procedure Edit (Document_Name : in String) is Document : Document_Type; begin -- Initialise the stack of bookmarks: Bookmark_Stacks.Create (S => Document.Bookmarks, Initial_Size => 10);