Az általános programozás egy olyan programozási paradigma , amely az adatok és algoritmusok olyan leírásából áll, amelyek különféle típusú adatokra alkalmazhatók anélkül, hogy magát a leírást megváltoztatnák. Ilyen vagy olyan formában különböző programozási nyelvek támogatják . Az általános programozási képességek először generikumok (általános függvények) formájában jelentek meg az 1970 -es években a Clu és Ada nyelvekben , majd parametrikus polimorfizmusként az ML -ben és leszármazottaiban, majd számos objektum-orientált nyelvben, mint például a C++ , Python [ 1] , Java , Object Pascal [2] , D , Eiffel , nyelvek a .NET platformhoz és mások.
Az általános programozást olyan programozási módszernek tekintik, amely az adatstruktúrák és algoritmusok elvont követelményleírások felhasználásával történő szétválasztásán alapul [3] . Az absztrakt követelmények deklarációi az absztrakt adattípus fogalmának kiterjesztései . Ahelyett, hogy egyetlen típust írnánk le az általános programozásban, egy olyan típuscsalád leírását használjuk, amelyek közös felülettel és szemantikai viselkedéssel rendelkeznek . Az interfészt és a szemantikai viselkedést leíró követelményrendszert koncepciónak nevezzük . Így egy általánosított stílusban megírt algoritmus bármely típusra alkalmazható, amely fogalmaival kielégíti. Ezt a lehetőséget polimorfizmusnak nevezzük .
Egy típusról azt mondjuk, hogy modellez egy fogalmat (egy fogalom modellje), ha kielégíti a követelményeit. Egy fogalom egy másik fogalom finomítása , ha az utóbbit kiegészíti. A koncepciókövetelmények a következő információkat tartalmazzák: [4]
A C++ nyelven az OOP virtuális függvényeken és öröklődésen keresztül, míg az OP (általános programozás) osztály- és függvénysablonokon keresztül valósul meg. Mindkét módszertan lényege azonban csak közvetve kapcsolódik konkrét megvalósítási technológiákhoz. Formálisabban az OOP altípus polimorfizmuson , míg az OP paraméteres polimorfizmuson alapul . Más nyelveken mindkettő másként valósítható meg. Például a CLOS multimetódusainak szemantikája hasonló a parametrikus polimorfizmushoz.
Masser és Stepanov a következő szakaszokat különbözteti meg a probléma megoldásában az OP módszertana szerint:
A minimalizálás és a keretezés célja olyan struktúra létrehozása, amely lehetővé teszi az algoritmusok függetlenségét az adott adattípusoktól. Ez a megközelítés tükröződik az STL könyvtár szerkezetében . [5]
Az általános programozás meghatározásának alternatív megközelítését, amelyet adattípusú generikus programozásnak nevezhetünk , Richard Bird és Lambert Meertens javasolta . Ebben az adattípus-struktúrák általános programok paraméterei. Ennek érdekében az absztrakció új szintjét vezetik be a programozási nyelvbe, nevezetesen a paraméterezést változó aláírású algebraosztályok tekintetében . Bár mindkét megközelítés elmélete független a programozási nyelvtől, a fogalomelemzést hangsúlyozó Musser-Stepanov megközelítés a C++ -t tette fő platformjává, míg az általános adattípusú programozást szinte kizárólag a Haskell és annak változatai alkalmazzák [6] .
Az általános programozási eszközöket a programozási nyelvekben bizonyos szintaktikai eszközök formájában valósítják meg, amelyek lehetővé teszik az adattípusok szerint paraméterezett adatok (adattípusok) és algoritmusok (eljárások, függvények, módszerek) leírását. Egy függvény vagy adattípus esetében a formális típusparaméterek kifejezetten le vannak írva . Ez a leírás általános, és nem használható közvetlenül az eredeti formájában.
A program azon helyein, ahol általános típust vagy függvényt használnak, a programozónak kifejezetten meg kell adnia a deklarációt meghatározó tényleges típusparamétert. Például egy általános eljárás két érték felcserélésére rendelkezhet egy típusparaméterrel, amely meghatározza a felcserélt értékek típusát. Amikor a programozónak két egész értéket fel kell cserélnie, akkor meghívja az eljárást az " integer " típusparaméterrel és két paraméterrel - egész számokkal, ha két karakterláncot - a " string " típusparaméterrel és két paraméterrel - stringeket. Adatok esetén a programozó például leírhat egy általános típusú " listát " egy típusparaméterrel, amely meghatározza a listában tárolt értékek típusát. Ezután a valós listák leírásánál a programozónak meg kell adnia egy általános típust és egy típus paramétert, így ugyanazzal a deklarációval megkapja a kívánt listát.
Amikor a fordító egy általános típus vagy függvény hívásával találkozik, elvégzi a szükséges statikus típusellenőrzési eljárásokat , kiértékeli egy adott példányosítás lehetőségét, és ha pozitív, kódot generál, a formális típusparaméter helyett a tényleges típusparamétert helyettesítve. az általános leírásban. Természetesen az általános leírások sikeres használatához a tényleges paramétertípusoknak bizonyos feltételeknek meg kell felelniük. Ha egy általános függvény egy típusparaméter értékeit hasonlítja össze, akkor a benne használt konkrét típusnak támogatnia kell az összehasonlítási műveleteket, ha típusparaméter értékeit rendeli a változókhoz, akkor a konkrét típusnak biztosítania kell a helyes hozzárendelést.
A C++ nyelvben az általános programozás a "sablon" fogalmán alapul, amelyet a template kulcsszó jelöl . Széles körben használják a C++ Standard Library-ben (lásd az STL -t), valamint a harmadik féltől származó könyvtárak boost -jában , a Loki -ban . Alexander Stepanov nagyban hozzájárult a fejlett általános programozási eszközök C++ nyelven való megjelenéséhez .
Példaként adjunk meg egy olyan függvény sablonját (általánosítását), amely a kettő nagyobb értékét adja vissza.
// Funkciósablonleíró sablon < típusnév T > T max ( T x , T y ) { ha ( x < y ) vissza y ; más visszatér x ; } ... // A sablon által megadott függvény alkalmazása int a = max ( 10 , 15 ); ... dupla f = max ( 123,11 , 123,12 ); ...vagy egy linkelt listaosztály sablonja (általánosítása):
sablon < classT > _ osztály listája { /* ... */ nyilvános : void Add ( const T & Element ); bool Find ( const T & Element ); /* ... */ };A Haskell általános adattípus-programozást biztosít. A következő példában a egy paraméteres típusú változó.
adatok Lista a = nulla | Cons a ( List a ) long :: List a -> Int long Nil = 0 long ( Cons _ tl ) = 1 + long tlSzámítási példa:
hossz ( Cons 1 ( Cons 2 Nil )) == 2A Java a J2SE 5.0 óta biztosítja a szintaktikailag C++-ra épülő általánosokat. Ennek a nyelvnek vannak generikus vagy "T típusú tárolói" - az általános programozás egy részhalmaza.
A .NET platformon általános programozási eszközök jelentek meg a 2.0-s verzióban.
// Egy általános osztály nyilatkozata. public class GenericList < T > { void Add ( T input ) { } } class TestGenericList { private class PéldaClass { } static void Main () { ÁltalánosLista < int > lista1 = new GenericList < int >(); GenericList < string > list2 = new GenericList < string >(); GenericList < ExampleClass > list3 = new GenericList < ExampleClass >(); } }Példa a D -sablonokon alapuló rekurzív generálásra :
// http://digitalmars.com/d/2.0/template.html template Foo ( T , R ...) // T egy típus, R típushalmaz { void Foo ( T t , R r ) { writeln ( t ); static if ( r . hossz ) // if more arguments Foo ( r ); // a többi argumentum elvégzése } } void main () { Foo ( 1 , 'a' , 6.8 ); } /++++++++++++++++ nyomatok: 1 -től 6,8- ig +++++++++++++++++/A Free Pascal fordító által nyújtott általános programozás támogatása a 2007 -es 2.2-es verzió óta elérhető [7] . Delphiben - 2008 októbere óta . Az általános osztályok alapvető támogatása először a Delphi 2007 .NET -ben jelent meg 2006 -ban , de csak a .NET-keretrendszert érintette . A Delphi 2009 teljesebb támogatást nyújtott az általános programozáshoz . Az általános osztályokat az Object Pascal is támogatja a PascalABC.NET rendszerben .