Ընդհանրացված ծրագրավորում
Ընդհանրացված ծրագրավորումը (անգլ.՝ generic programming) ծրագրավորման պարադիգմ է, որը բաղկացած է տվյալների և ալգորիթմների նկարագրությունից, որոնք կարող են կիրառվել տարբեր տեսակի տվյալների վրա՝ առանց այդ նկարագրությունը փոխելու։ Այն այս կամ այն ձևով աջակցվում է տարբեր ծրագրավորման լեզուներով: Ընդհանրացված ծրագրավորման հնարավորությունները առաջին անգամ հայտնվեցին ջեներիկների(ընդհանրացված ֆունկցիաների) տեսքով 1970-ականներին Clu-ում և Ada-ում, այնուհետև պարամետրային պոլիմորֆիզմի տեսքով ML-ում և նրա հետնորդներում, այնուհետև շատ օբյեկտ կողմնորոշված լեզուներում, ինչպիսիք են C++, Python[1], Java, Object Pascal[2], D, Eiffel, լեզուներ .NET պլատֆորմի համար և այլն:
Մեթոդաբանություն
[խմբագրել | խմբագրել կոդը]Ընդհանրացված ծրագրավորումը դիտարկվում է որպես ծրագրավորման մեթոդաբանություն, որը հիմնված է տվյալների կառուցվածքների և ալգորիթմների տարանջատման վրա՝ պահանջների աբստրակտ նկարագրությունների կիրառմամբ[3]: Աբստրակտ պահանջների նկարագրությունները աբստրակտ տվյալների տիպի հասկացության ընդլայնումն են: Մեկ տեսակ նկարագրելու փոխարեն ընդհանրացված ծրագրավորման մեջ օգտագործվում է տիպերի ընտանիքի նկարագրությունը, որոնք ունեն ընդհանուր ինտերֆեյս և իմաստային վարքագիծ (անգլ.՝ semantic behavior)։ Պահանջների ամբողջությունը, որոնք նկարագրում են ինտերֆեյսը և իմաստային վարքագիծը, կոչվում է կոնցեպցիա (concept): Այսպիսով, ընդհանրացված ոճով գրված ալգորիթմը կարող է օգտագործվել ցանկացած տիպի համար։ Այդպիսի հատկանիշը կոչվում է պոլիմորֆիզմ։
Ասում են, որ տիպը մոդելավորում է կոնցեպցիան (կոնցեպցիայի մոդել է), եթե այն բավարարում է դրա պահանջներին: Կոնցեպցիանը մեկ այլ կոնցեպցիայի հստակեցումն է, եթե այն լրացնում է վերջինս: Կոնցեպցիայի պահանջները պարունակում են հետևյալ տեղեկությունները
- Թույլատրելի արտահայտությունները (անգլ.՝ valid expressions) ծրագրավորման լեզուների արտահայտություններ են, որոնք պետք է հաջողությամբ կոմպիլյացվեն կոնցեպցիան մոդելավորող տիպերի համար:
- Ասոցիացված տիպեր (associated types) օժանդակ տիպեր են, որոնք որոշակի կապ ունեն կոնցեպցիան մոդելավորող տիպի հետ:
- Ինվարիանտները(invariants) տիպերի բնութագրիչներ են, որոնք միշտ պետք է ճշմարիտ լինեն կատարման ժամանակ: Սովորաբար արտահայտվում է նախապայմանների և հետպայմանների տեսքով։ Նախապայմանին չբավարարելը հանգեցնում է համապատասխան գործողության անկանխատեսելիության և կարող է հանգեցնել սխալների:
- Բարդության երաշխիքներ(complexity guarantees) թույլատրելի արտահայտության առավելագույն կատարման ժամանակն է
C++ լեզվում օբյեկտ կողմնորոշված ծրագրավորումը (ՕԿԾ) իրականացվում է վիրտուալ ֆունկցիաների և ժառանգման միջոցով, մինչդեռ ընդհանրացված ծրագրավորումը իրականացվում է դասի շաբլոնների և ֆունկցիաների միջոցով: Այնուամենայնիվ, երկու մեթոդաբանությունների էությունը միայն անուղղակիորեն է կապված կոնկրետ իրականացման տեխնոլոգիաների հետ: ՕԿԾ-ն հիմնված է ենթատիպային պոլիմորֆիզմի վրա, մինչդեռ ընդհանրացված ծրագրավորումը հիմնված է պարամետրային պոլիմորֆիզմի վրա: Այլ լեզուներում երկուսն էլ կարող են այլ կերպ իրականացվել: Օրինակ, CLOS-ում մուլտիմեթոդներն ունեն պարամետրային պոլիմորֆիզմի նման իմաստ։
Մասերը և Ստեպանովը առանձնացնում են ընդհանրացված ծրագրավորման մեթոդաբանության խնդրի լուծման հետևյալ փուլերը:
- Գտնել օգտակար և արդյունավետ ալգորիթմ:
- Սահմանել ընդհանրացված ներկայացում (պարամետրացնել ալգորիթմը ՝ նվազագույնի հասցնելով մշակվող տվյալների պահանջները:
- Նկարագրել մի շարք (նվազագույն) պահանջներ, որոնք բավարարելով, դուք դեռ կարող եք ստանալ արդյունավետ ալգորիթմներ:
- Ստեղծեք շրջանակ՝ հիմնված դասակարգված պահանջների վրա:
Նվազագույնի հասցնելը և շրջանակի ստեղծումը նպատակ ունեն ստեղծել այնպիսի կառուցվածք, որում ալգորիթմները կախված չեն տվյալների հատուկ տիպերից:Այս մոտեցումը արտացոլված է STL գրադարանի կառուցվածքում։
Ընդհանրացված ծրագրավորման սահմանման այլընտրանքային մոտեցում է՝ տվյալների տիպի ընդհանրացված ծրագրավորումը (անգլ. datatype generic programming), որն առաջարկվել է Ռիչարդ Բիրդի և Լամբերտ Մերտենսի կողմից։ Դրանում տվյալների տիպի կառուցվածքները ընդհանրացված ծրագրերի պարամետրեր են: Դրա համար ծրագրավորման լեզվում ներդրվում է աբստրակցիայի նոր մակարդակ, այն է՝ պարամետրացում՝ կապված փոփոխականի գրելաձևով հանրահաշվական դասերի հետ։ Թեև երկու մոտեցումների տեսությունները կախված չեն ծրագրավորման լեզվից, Մասեր-Ստեպանովի մոտեցումը, որը շեշտը դնում է կոնցեպցիայի վերլուծության վրա, C++ ծրագրավորման լեզուն դարձրել է իր հիմնական հարթակը, մինչդեռ ընդհանրացված տվյալների տիպի ծրագրավորումն օգտագործում է գրեթե բացառապես Haskell-ը և դրա տարբերակները։
Ընդհանուր մեխանիզմ
[խմբագրել | խմբագրել կոդը]Ընդհանրացված ծրագրավորման գործիքներն իրականացվում են ծրագրավորման լեզուներում որոշակի շարահյուսական միջոցների տեսքով, որոնք հնարավորություն են տալիս նկարագրել տվյալները(տվյալների տեսակները) և ալգորիթմները (կոնցեպցիաներ, ֆունկցիաներ, մեթոդներ), որոնք պարամետրացվում են տվյալների տիպերի կողմից: Ֆունկցիան կամ տվյալների տիպը հստակ նկարագրում են ֆորմալ պարամետրերը՝ տիպերը: Այս նկարագրությունը ընդհանրացված է և չի կարող ուղղակիորեն օգտագործվել իր սկզբնական տեսքով:
Ծրագրի այն վայրերում, որտեղ օգտագործվում է ընդհանրացված տիպը կամ ֆունկցիան, ծրագրավորողը պետք է հստակ նշի իրական պարամետրը՝ նկարագրությունը բնութագրող տիպը: Օրինակ, երկու արժեքների վերադասավորման ընդհանրացված ֆունկցիան կարող է ունենալ պարամետր-տիպ, որը սահմանում է այն արժեքների տիպը, որը այն փոխում է: Երբ ծրագրավորողը պետք է փոխի երկու ամբողջ արժեք, նա կանչում է «ամբողջ թիվ» տիպի պարամետրով ֆունկցիան և երկու պարամետրով՝ ամբողջ թվեր, երբ երկու տող՝ «տող» տիպի պարամետրով և երկու պարամետրով՝ տողերով: Տվյալների դեպքում ծրագրավորողը կարող է, օրինակ, նկարագրել «ցուցակ» ընդհանրացված տեսակը՝ տիպ պարամետրով, որը սահմանում է ցուցակում պահվող արժեքների տիպը: Այնուհետև իրական ցուցակները նկարագրելիս ծրագրավորողը պետք է նշի ընդհանրացված տիպը և պարամետր-տեսակը ՝ այդպիսով ստանալով ցանկացած ցանկալի ցուցակ ՝ օգտագործելով նույն նկարագրությունը:
Կոմպիլյատորը, հանդիպելով ընդհանրացված տիպին կամ ֆունկցիայի կանչին, կատարում է ստատիկ տիպի ստուգման անհրաժեշտ վերահսկողությունները, գնահատում է տվյալի կոնկրետացման հնարավորությունը և դրական գնահատման դեպքում գեներացնում է կոդ՝ փոխարինելով իրական տիպի պարամետրը ֆորմալ տիպի պարամետրին ընդհանրացված նկարագրության մեջ: Բնականաբար, ընդհանրացված նկարագրությունները հաջողությամբ օգտագործելու համար պետք է իրական պարամետրերի տիպերը բավարարեն որոշակի պայմաններին: Եթե ընդհանրացված ֆունկցիան համեմատում է պարամետրի տիպի արժեքները, ապա դրա մեջ օգտագործվող ցանկացած տիպ պետք է աջակցի համեմատման գործողություններին, եթե այն վերագրում է պարամետր-տիպի արժեքները փոփոխականներին, այն պետք է իրականացնի ճիշտ վերագրում:
Ընդհանրացված ծրագրավորումը լեզուներում
[խմբագրել | խմբագրել կոդը]C++
[խմբագրել | խմբագրել կոդը]C++ լեզվում ընդհանրացված ծրագրավորումը հիմնված է «շաբլոն» հասկացողության վրա, որը սկսվում է template բանալի բառով։ Լայնորեն կիրառվում է C++ շաբլոնների ստանդարտ գրադարանում, ինչպես նաև կողմնակի boost, Loki գրադարաններում։ Ալեքսանդր Ստեպանովը մեծ ներդրում ունեցավ C++ ծրագրավորման լեզվում ընդհանրացված ծրագրավորման զարգացման գործում։
Որպես օրինակ՝ բերենք ֆունկցիայի շաբլոն (ընդհանրացում), որը վերադարձնում է երկու արժեքներից մեծագույնը։
// Շաբլոն ֆունկցիայի նկարագրություն
template <typename T> T max(T x, T y)
{
if (x < y)
return y;
else
return x;
}
...
// Շաբլոնով տրված ֆունկցիայի կիրառում
int a = max(10,15);
...
double f = max(123.11, 123.12);
...
կամ կապակցված ցուցակի դասի շաբլոն (ընդհանրացում).
template <class T>
class List
{
/* ... */
public:
void Add( const T& Element );
bool Find( const T& Element );
/* ... */
};
Haskell
[խմբագրել | խմբագրել կոդը]Haskell լեզուն ապահովում է տվյալների տիպերի ընդհանրացված ծրագրավորում: Հետևյալ օրինակում a-ն պարամետրային տիպի փոփոխական է:
data List a = Nil | Cons a (List a)
length :: List a -> Int
length Nil = 0
length (Cons _ tl) = 1 + length tl
Հաշվարկի օրինակ․
length (Cons 1 (Cons 2 Nil)) == 2
Java
[խմբագրել | խմբագրել կոդը]Java-ն տրամադրում է ընդհանրացված ծրագրավորման գործիքներ, որոնք շարահյուսորեն հիմնված են C++ լեզվի վրա՝ սկսած J2SE 5.0 տարբերակից։ Այս լեզվում կան generics կամ «T տիպի կոնտեյներներ»՝ ընդհանրացված ծրագրավորման ենթաբազմություն։
.NET
[խմբագրել | խմբագրել կոդը]. Net պլատֆորմում ընդհանրացված ծրագրավորման գործիքները հայտնվել են 2.0 տարբերակում։
// Ընդհանրացված դասի հայտարարում
public class GenericList<T>
{
void Add(T input) { }
}
class TestGenericList
{
private class ExampleClass { }
static void Main()
{
GenericList<int> list1 = new GenericList<int>();
GenericList<string> list2 = new GenericList<string>();
GenericList<ExampleClass> list3 = new GenericList<ExampleClass>();
}
}
Օրինակ C# լեզվում
[խմբագրել | խմբագրել կոդը]interface IPerson
{
string GetFirstName();
string GetLastName();
}
class Speaker
{
public void SpeakTo<T>(T person) where T : IPerson
{
string name = person.GetFirstName();
this.say("Hello, " + name);
}
}
D
[խմբագրել | խմբագրել կոդը]D լեզվի շաբլոնների վրա հիմնված ռեկուրսիվ գեներացիայի օրինակ.
// http://digitalmars.com/d/2.0/template.html
template Foo(T, R...) // T - тип, R - набор типов
{
void Foo(T t, R r)
{
writeln(t);
static if (r.length) // if more arguments
Foo(r); // do the rest of the arguments
}
}
void main()
{
Foo(1, 'a', 6.8);
}
/+++++++++++++++
prints:
1
a
6.8
+++++++++++++++/
Object Pascal
[խմբագրել | խմբագրել կոդը]Free Pascal կոմպիլյատորում ընդհանրացված ծրագրավորման աջակցությունը հայտնվել է 2007 թվականի 2.2 տարբերակից սկսած[4]: Դելֆիում՝ 2008 թվականի հոկտեմբերից։ Ընդհանրացված դասի աջակցությունն առաջին անգամ հայտնվեց Delphi 2007 .NET-ում 2006 թվականին, բայց այն ազդեց միայն .NET Framework-ի վրա: Ավելի ամբողջական աջակցություն ընդհանրացված ծրագրավորմանը ավելացվել է Delphi 2009-ում։ Ընդհանրացված դասերը նույնպես աջակցվում են Object Pascal-ում PascalABC.NET համակարգում:
Nim
[խմբագրել | խմբագրել կոդը]import typetraits
proc getType[T](x: T): string =
return x.type.name
echo getType(21) # կարտածի int
echo getType(21.12) # կարտածի float64
echo getType("string") # կարտածի string
Ծանոթագրություններ
[խմբագրել | խմբագրել կոդը]- ↑ «Python Generic». Արխիվացված է օրիգինալից 2021-02-09-ին. Վերցված է 2020-05-28-ին.
{{cite web}}
: Unknown parameter|deadurl=
ignored (|url-status=
suggested) (օգնություն) - ↑ В Delphi и PascalABC.NET
- ↑ Сик, Ли, Ламсдэйн, 2006, էջ 47—48
- ↑ «Freepascal.Generics». Արխիվացված է օրիգինալից 2010-12-15-ին. Վերցված է 2011-02-01-ին.
{{cite web}}
: Unknown parameter|deadurl=
ignored (|url-status=
suggested) (օգնություն)
Հղումներ
[խմբագրել | խմբագրել կոդը]- generic-programming.org Արխիվացված 2020-11-06 Wayback Machine(անգլ.)
- Gabriel Dos Reis and Jaakko Järvi, What is Generic Programming?
- Обобщённое программирование в Delphi(ռուս.)
Գրականություն
[խմբագրել | խմբագրել կոդը]- Джереми Сик, Лай-Кван Ли, Эндрю Ламсдэйн. C++ Boost Graph Library. — Питер, 2006. — 304 с. — ISBN 5-469-00352-3
- Степанов Александр А., Роуз Дэниэл Э. От математики к обобщённому программированию. — ДМК Пресс, 2016. — 264 с. — ISBN 978-5-97060-379-6