Шаблонни типове

от Уикипедия, свободната енциклопедия
Направо към навигацията Направо към търсенето

Шаблонни типове са концепция за типизиране на параметри в програмирането. Те позволяват да се изработват класове и методи, които да отложат спецификацията на един или повече типове данни, докато един клас или метод не се декларира и не получи своята инстанция. Например, чрез използване на шаблонен тип параметър T може да се напише един клас, който друг код също може да използва, без да понесе забавяне на времето на работа.

Този подход, измислен за първи път излиза чрез ML през 1973 г., позволява написването общите функции или типове, които се различават само определения тип данни с който работят, когато се използва, по този начин се намалява дублирането. Такива софтуерни обекти, са известни като шаблонни типове в Ada, Delphi, Eiffel, Java, C#, F# и Visual Basic .NET;. Параметричен полиморфизъм в ML, Scala и Haskell (общността Haskell също използва подобно "родово" свързано(шаблонно свързване), но донякъде с различна концепция); шаблонните в C++ и D; и параметризирани типове в книгата от 1994 Design Patterns. Авторите на Design Patterns, обръщат внимание на това, че тази техника, особено когато се комбинира с опълномощяване е много мощна, но този "динамичен и силно зададен с параметри софтуер е по-труден да се разбере от по-статичния такъв"."[1]

Терминът родово програмиране е въведен първоначално от Дейвид Musser и Александър Степанов [2] За да се опише програмиращата парадигма, при която абстрахират основните изисквания към типовете данни от целите конкретни примери на алгоритмите и структури от данни, формализирани в концепции, с общи функции, изпълнявани от гледна точка на тези понятия. Обикновено използвайки механизми език родството (наследствеността на обектите), най-вече използвани в изброените по горе езици.

Езици за програмиране които поддържат родствените/наследствените типове (шаблонни)[редактиране | редактиране на кода]

Родовите типове са имплементирани в езици от високо ниво още от 1970 г. в езици като CLU и Ada, и впоследствие са приети от много обектно-базирани и обектно-ориентирани езици, включително BETA, C++, D, Eiffel, Java, и на DEC вече несъществуващия Trellis-Owl език. Реализации на шаблонните/наследствени типове в езиците като Java и C# са официално въз основа на идеята за параметрите(parametricity), породена от John C. Reynolds.

Наследствеността се прилага и се поддържа по различен начин в различните езици за програмиране, терминът "родов"/"наследстен" се използва по различен начин в различните ситуации в програмиране. Например, в Forth компилаторът може да изпълни код в процеса на компилиране и може да създадат нови ключови думи. Той има няколко думи, които излагат на компилатора поведението и следователно естествено предлага наследствения капацитет, който, обаче, не е посочен като такъв в повечето Forth текстове. Терминът се използва в Функционално програмиране, по-специално в Haskell подобните езици, които използват структурна система на типовете. Тези инструменти все още служат за подобна цел, а именно спестяване на код и оказване на абстракция.

Масивите(arrays) и структурите(structs) може да се разглежда като предварително определени шаблонни типове. Всяко използване на масив или структура като тип ни дават конкретен пример за типове чието използване повторно се инстанцира от един родов/наследствен тип. Вида на елементите от масива и вида на елементите на структурата са параметризирани типове, които се използват за конкретни примери съответни си с родовия си общ тип. Всичко това обикновено е вградено в компилатора и синтаксис го различава от другите общи структури. Някои по-обширни езици за програмиране се опитват да обединят вградените типове и потребителски дефинираните шаблонни типове.

Шаблонни типове в обектно ориентираните езици[редактиране | редактиране на кода]

Шаблонни типове в Java[редактиране | редактиране на кода]

Поддръжка на шаблонните типове или "контейнери-на-тип-Т" се прибавят към програмния език Java programming language през 2004 г. като част от J2SE 5.0. В Java шаблонните типове се проверяват само по време на компилация за това дали са от коректен тип. Информацията за типа се отстранява впоследствие чрез процес, наречен “изтриване на тип”(type erasure), с цел да се продължи поддържаната съвместимост със стари JVM приложения, правещ го недостъпен по време на работа. Например, List<String> се превръща в първичен тип List. Компилатора вкарва кастване на типовете за да превърне елементите в String тип когато са потърсени в List-а което намалява производителността в сравнение с имплементацията на шаблонните типове в C++.

Шаблонни типове в C#[редактиране | редактиране на кода]

Шаблонните типове се добавят като част от .NET Framework 2.0 през ноември 2005 г., базирана въз основа на изследвания прототип от Microsoft Research започнал през 1999 година[2]. Въпреки че са подобни на тези в Java, NET шаблонните типове не предлагат изтриване типове, но се използват като първокласен механизъм за работа на програмите чрез използване на абстракция за използване на данните. Този дизайнерски подход осигурява допълнителна функционалност. Това също така означава, че няма удар по производителността и бързодействието от допълнителните кастове и обхващащите ги операции. Когато примитивни и стойностни типове се използват като шаблонни аргументи, те ще получат специална имплементация, позволяващи наличието на ефективни шаблонни колекции и методи. Както и в C + + и Java, вложените шаблонни типове като Dictionary <низ, Списък <int>> са валидни типове.

. NET позволява шест разновидности на ограничения за шаблоните типове като използване на ключови думи, включващо в себе си ограниченито че определени родови типове не могат да бъдат стойностни типове данни, класове, да имат конструктори, или да въвеждат интерфейси. По-долу е пример с интерфейсно ограничение.:

using System;

class Sample {
    static void Main() {
        int[] array = { 0, 1, 2, 3 };
        MakeAtLeast<int>(array, 2); // Change array to { 2, 2, 2, 3 }
        foreach (int i in array)
            Console.WriteLine(i); // Print results.
        Console.ReadKey(true);
    }

    static void MakeAtLeast<T>(T[] list, T lowest) where T : IComparable<T> {
        for (int i = 0; i < list.Length; i++)
            if (list[i].CompareTo(lowest) < 0)
                list[i] = lowest;
    }
}

MakeAtLeast() методa позволява работа със масиви, с елементи от шаблонен тип T. Ограничението от вида на метода е, че методът е приложим за всякакъв тип T, който имплементира в себе си IComparable интерфейс IComparable<T>. Това осигурява грешка при компилация, ако извиканият метод не поддържа сравнение. Интерфейсът осигурява шаблонен(наследствен) метод CompareTo(T).

Горният метод може да се запише и без шаблонни типове, просто като се използва не-шаблонния тип Array. Въпреки това, тъй като масиви са контра вариант, кастването не би било безопасно за типа и компилатора може да пропусне грешки, които иначе биха били уловени при използването на шаблонен тип. В допълнение, методът ще трябва да имат достъп до елементите на масива, но като обекти, а и ще изисква кастване за да се сравнят два елемента.

Важен поведение на статичните членове в шаблонния . NET клас е инстанцията на статичния член на типа по време на изпълнение (виж примера по-долу).

    //A generic class
    public class GenTest<T>
    {
        //A static variable&nbsp;— will be created for each type on refraction
        static CountedInstances OnePerType = new CountedInstances();

        //a data member
        private T mT;

        //simple constructor
        public GenTest(T pT)
        {
            mT = pT;
        }
    }

    //a class
    public class CountedInstances
    {
        //Static variable&nbsp;— this will be incremented once per instance
        public static int Counter;

        //simple constructor
        public CountedInstances()
        {
            //increase counter by one during object instantiation
            CountedInstances.Counter++;
        }
    }

  //main code entry point
  //at the end of execution, CountedInstances.Counter = 2
  GenTest<int> g1 = new GenTest<int>(1);
  GenTest<int> g11 = new GenTest<int>(11);
  GenTest<int> g111 = new GenTest<int>(111);
  GenTest<double> g2 = new GenTest<double>(1.0);

Шаблонни типове в C++[редактиране | редактиране на кода]

C ++ използва шаблони за да се разреши използването на шаблонни техники на програмиране. Стандартната библиотека в C++ включва Стандартна шаблонна библиотека (Standard Template Library или STL), тя предоставя рамка от шаблони за общи структури от данни и алгоритми. Шаблоните в C ++ могат да се използват за шаблонно метапрограмиране (template metaprogramming), което е начин за предварително оценяване на част от кода по време на компилация, а не по време на изпълнение.

Видове шаблони[редактиране | редактиране на кода]

Има два вида шаблони: шаблонни функции и шаблонни класове. Шаблонната функция е модел за създаване на обикновени функции въз основа на задаване на параметризирани типове данни доставени на функцията при инстанциране. Така например, C + + STL съдържа в себе си функцията max(x, y), която създава функция, която връща X или Y, в зависимост от това кое е по-голямо larger. max() може да се определи по следния начин:

template <typename T>
T max(T x, T y)
{
    return x < y ? y : x;
}

Специализациите на тoзи функционален шаблон, инстанциите на специфичните типове, могат да бъдат извикани просто като обикновена функция

cout << max(3, 7); // Връща 7

Компилаторът разглежда използваните за извикването на функцията max аргументи и определя, че това е извикване именно към max(int, int). След което се инстанцира версия на функцията където зададения като параметър тип T е int, правейки еквивалентна функция :

int max(int x, int y)
{
    return x < y ? y : x;
}

Източници[редактиране | редактиране на кода]