Generické programování

Aktuální verze stránky ještě nebyla zkontrolována zkušenými přispěvateli a může se výrazně lišit od verze recenzované 20. července 2022; ověření vyžaduje 1 úpravu .

Generické programování je programovací paradigma ,  které spočívá v takovém popisu dat a algoritmů , které lze aplikovat na různé typy dat, aniž by se měnil samotný popis. V té či oné podobě je podporován různými programovacími jazyky . Schopnosti generického programování se poprvé objevily ve formě generik (generických funkcí) v 70. letech v jazycích Clu a Ada , poté jako parametrický polymorfismus v ML a jeho potomcích a poté v mnoha objektově orientovaných jazycích, jako je C++ , Python [ 1] , Java , Object Pascal [2] , D , Eiffel , jazyky pro platformu .NET a další.

Obecná metodika programování

Generické programování je považováno za metodologii programování založenou na oddělení datových struktur a algoritmů pomocí abstraktních popisů požadavků [3] . Abstraktní deklarace požadavků jsou rozšířením konceptu abstraktního datového typu . Místo popisu jednoho typu v generickém programování se používá popis rodiny typů, které mají společné rozhraní a sémantické chování .  Sada požadavků, které popisují rozhraní a sémantické chování , se nazývá koncept . Algoritmus napsaný zobecněným stylem lze tedy aplikovat na jakýkoli typ, který jej svými koncepty splňuje. Tato možnost se nazývá polymorfismus .  

O typu se říká, že modeluje koncept (je modelem konceptu), pokud splňuje jeho požadavky. Koncept je zdokonalením jiného konceptu, pokud jej doplňuje. Koncepční požadavky obsahují následující informace: [4]

V C++ je OOP implementován prostřednictvím virtuálních funkcí a dědičnosti, zatímco OP (generic programming) je implementován prostřednictvím šablon tříd a funkcí. Podstata obou metodik však souvisí s konkrétními implementačními technologiemi pouze nepřímo. Formálněji je OOP založen na polymorfismu podtypu , zatímco OP je založen na parametrickém polymorfismu . V jiných jazycích mohou být oba implementovány odlišně. Například multimetody v CLOS mají sémantiku podobnou parametrickému polymorfismu.

Masser a Stepanov rozlišují následující fáze řešení problému podle metodiky OP:

  1. Najděte užitečný a efektivní algoritmus.
  2. Definujte zobecněnou reprezentaci (parametrizujte algoritmus, minimalizujte požadavky na zpracovávaná data).
  3. Popište sadu (minimálních) požadavků, které mohou stále poskytovat efektivní algoritmy.
  4. Vytvořte drátěný model na základě klasifikovaných požadavků.

Cílem minimalizace a rámování je vytvořit takovou strukturu, aby byly algoritmy nezávislé na konkrétních typech dat. Tento přístup se odráží ve struktuře knihovny STL . [5]

Alternativní přístup k definování generického programování, který lze nazvat datovým generickým programováním , navrhli Richard Bird a Lambert Meertens .  V něm jsou struktury datových typů parametry generických programů. K tomu je do programovacího jazyka zavedena nová úroveň abstrakce, a to parametrizace s ohledem na třídy algeber s proměnnou signaturou . Přestože teorie obou přístupů jsou nezávislé na programovacím jazyce, přístup Musser-Stepanov, který klade důraz na analýzu konceptů, učinil C++ svou hlavní platformou, zatímco programování generických datových typů používá téměř výhradně Haskell a jeho varianty [6] .

Obecný mechanismus

Generické programovací nástroje jsou implementovány v programovacích jazycích ve formě určitých syntaktických prostředků, které umožňují popisovat data (datové typy) a algoritmy (procedury, funkce, metody) parametrizované datovými typy. Pro funkci nebo datový typ jsou explicitně popsány parametry formálního typu . Tento popis je zobecněný a nelze jej přímo použít v původní podobě.

Na těch místech v programu, kde se používá generický typ nebo funkce, musí programátor explicitně specifikovat parametr skutečného typu, který specifikuje deklaraci. Například obecný postup pro záměnu dvou hodnot může mít parametr typu, který určuje typ hodnot, které zaměňuje. Když programátor potřebuje prohodit dvě celočíselné hodnoty, zavolá proceduru s parametrem typu " integer " a dvěma parametry - celá čísla, když dva řetězce - s parametrem typu " řetězec " a dvěma parametry - řetězce. V případě dat může programátor například popsat generický typ „ list “ pomocí parametru typu, který určuje typ hodnot uložených v seznamu. Poté, když popisuje skutečné seznamy, musí programátor specifikovat generický typ a parametr typu, čímž získá libovolný požadovaný seznam pomocí stejné deklarace.

Když kompilátor narazí na volání generického typu nebo funkce, provede nezbytné procedury kontroly statického typu , vyhodnotí možnost dané instance, a pokud je pozitivní, vygeneruje kód, který nahradí parametr skutečného typu místo parametru formálního typu. v obecném popisu. Pro úspěšné použití generických popisů musí samozřejmě aktuální typy parametrů splňovat určité podmínky. Pokud generická funkce porovnává hodnoty parametru typu, jakýkoli konkrétní typ použitý v ní musí podporovat operace porovnání, pokud přiřazuje hodnoty parametru typu proměnným, musí konkrétní typ zajistit správné přiřazení.

Generické programování v jazycích

C++

V C++ je obecné programování založeno na konceptu „šablony“, označené klíčovým slovem template . Je široce používán ve standardní knihovně C++ (viz STL ) a také v knihovnách třetích stran boost , Loki . Velkým přínosem pro vznik pokročilých generických programovacích nástrojů v C++ byl Alexander Stepanov .

Jako příklad uveďme šablonu (zobecnění) funkce, která vrací větší hodnotu ze dvou.

// Šablona popisu šablony funkce < typename T > T max ( T x , T y ) { pokud ( x < y ) vrátit y ; jiný návrat x ; } ... // Použití funkce dané šablonou int a = max ( 10 , 15 ); ... dvojité f = max ( 123,11 , 123,12 ); ...

nebo šablonu (zobecnění) třídy propojeného seznamu:

šablona < classT > _ třída Seznam { /* ... */ veřejnost : void Přidat ( const T & Element ); bool Najít ( const T & Element ); /* ... */ };

Haskell

Haskell poskytuje generické programování datových typů. V následujícím příkladu a proměnná parametrického typu.

seznam dat a = nula | Nevýhody a ( Seznam a ) délka :: Seznam a -> Délka Int Nil = 0 délka ( Nevýhody _ tl ) = 1 + délka tl

Příklad výpočtu:

délka ( Nevýhody 1 ( Nevýhody 2 Nil )) == 2

Java

Java poskytuje generika, která jsou syntakticky založena na C++ od J2SE 5.0. Tento jazyk má generika nebo „kontejnery typu T“ – podmnožinu generického programování.

.NET

Na platformě .NET se ve verzi 2.0 objevily generické programovací nástroje.

// Deklarace generické třídy. public class GenericList < T > { void Add ( T input ) { } } class TestGenericList { private class ExampleClass { } static void Main () { GenericList < int > seznam1 = new GenericList < int >(); GenericList < string > list2 = new GenericList < string >(); GenericList < ExampleClass > seznam3 = new GenericList < ExampleClass >(); } }

Příklad v C#

interface IPperson { string GetFirstName (); string GetLastName (); } class Speaker { public void SpeakTo < T > ( T person ) kde T : IPerson { string name = person . GetFirstName (); toto . řekněte ( "Dobrý den, " + jméno ); } }

D

Příklad rekurzivního generování založeného na D šablonách :

// http://digitalmars.com/d/2.0/template.html template Foo ( T , R ...) // T je typ, R je množina typů { void Foo ( T , R r ) { writeln ( t ); static if ( r . length ) // if více argumentů Foo ( r ); // proveďte zbytek argumentů } } void main () { Foo ( 1 , 'a' , 6.8 ); } /++++++++++++++++ tisky: 1 a 6,8 +++++++++++++++++/

ObjectPascal

Podpora pro generické programování kompilátorem Free Pascal je dostupná od verze 2.2 v roce 2007 [7] . V Delphi  - od října 2008 . Základní podpora pro generické třídy se poprvé objevila v Delphi 2007 .NET v roce 2006 , ale ovlivnila pouze .NET Framework . V Delphi 2009 byla přidána úplnější podpora pro generické programování . Obecné třídy jsou také podporovány v Object Pascalu v systému PascalABC.NET .

Nim

importovat typové znaky proc getType [ T ] ( x : T ): řetězec = vrátit x . typ . název echo getType ( 21 ) # vytiskne int echo getType ( 21.12 ) # vytiskne float64 echo getType ( "string" ) # vytiskne řetězec

Poznámky

  1. Python Generic . Získáno 28. května 2020. Archivováno z originálu dne 9. února 2021.
  2. V Delphi a PascalABC.NET
  3. Sik, Lee, Lumsdane, 2006 , str. 39.
  4. Sik, Lee, Lumsdane, 2006 , str. 47-48.
  5. Sik, Lee, Lumsdane, 2006 , str. 40-45.
  6. Gabriel Dos Reis, Jaakko Järvi. Co je generické programování?
  7. Freepascal Generics . Získáno 1. února 2011. Archivováno z originálu 15. prosince 2010.

Odkazy

Literatura

  • Jeremy Sik, Lai Kwang Lee, Andrew Lumsdane. Knihovna grafů Boost C++. - Petr, 2006. - 304 s. — ISBN 5-469-00352-3 .
  • Stepanov Alexander A., ​​​​Rose Daniel E. Od matematiky k obecnému programování. - DMK Press, 2016. - 264 s. - ISBN 978-5-97060-379-6 .