Մասնակից:MHamlet/Սևագրություն/2

Վիքիպեդիայից՝ ազատ հանրագիտարանից

Ծրագրավորման լեզուներում և տիպերի տեսության մեջ պոլիմորֆիզմ են անվանում տարբեր տիպ ունեցող տվյալների միանման մշակումը։

Գոյություն ունեն պոլիմորֆիզմի մի քանի սկզբունքորեն տարբեր տեսակներ, որոնցից երկուսը նկարագրված են եղել Քրիստոֆեր Ստրեչի կողմից 1967թ․։

Եթե ֆունկցիան նկարագրում է հստակ նկարագրված տիպերի և նրանց կոմբինացիաների սահմանափակ խմբերի տարբեր իրականացումներ (հնարավոր է, տարբեր պահվածքներով), դա անվանում են իրավիճակային պոլիմորֆիզմ (ad hoc polimorphism)։ Իրավիճակային պոլիմորֆիզմն աջակցվում է շատ լեզուներում ֆունկցիաների և մեթոդների վերբեռնման միջոցով։

Եթե կոդը գրված է կոնկրետ տվյալների տիպերից անկախ և, ինչի հետևանքով, կարող է ազատ օգտագործվել ցանկացած նոր տիպերի հետ, անվանում են պարամետրական պոլիմորֆիզմ։ Ջոն Ս․ Ռեյնոլդսը և, նրանից անկախ, Ժան-Իվ Ժիրարը, նկարագրեցին այդ նշանակումը որպես լամբդա-հաշվման զագացում (որն անվանում են պոլիմորֆ լամբդա-հաշիվ կամ F համակարգ)։ Պարամետրական պոլիմորֆիզմն լայնորեն կիրառվում է ստատիկ տիպավորմամբ ֆունկցիոնալ ծրագրավորման լեզուներում։ Օբյեկտային կողմնորոշված համայնքներում պարամետրիկ պոլիմորֆիզմի կիրառմամբ ծրագրավորումն անվանում են ընդհանրացված ծրագրավորում։

Պոլիմորֆիզմը համարվում է տիպերի համակարգի հիմնարար հատկություն։ Հաճախ տարբերում են ստատիկ ոչ պոլիմորֆ տիպավորում (Angol-ի և BCPL-ի հետնորդները), դինամիկ տիպավորում (Lisp-ի, Smalltalk-ի, APL-ի հետնորդները) և ստատիկ պոլիմորֆ տիպավորումը (ML-ի հետնորդները)։ В наибольшей степени применение ad hoc полиморфизма присуще при неполиморфной типизации, параметрического — при полиморфной. Параметрический полиморфизм и динамическая типизация намного существеннее, чем ситуативный полиморфизм, повышают коэффициент повторного использования кода, поскольку определенная единственный раз функция реализует без дублирования заданное поведение для бесконечного множества вновь определяемых типов, удовлетворяющих требуемым в функции условиям.

Некоторые языки совмещают различные формы полиморфизма, порой сложным образом, что формирует самобытную идеологию в них и влияет на применяемые методологии декомпозиции задач. Например, в Smalltalk любой класс способен принять сообщения любого типа, и либо обработать его самостоятельно (в том числе посредством интроспекции), либо ретранслировать другому классу — таким образом, несмотря на широкое использование перегрузки функций, формально любая операция является неограниченно полиморфной и может применяться к данным любого типа.

В объектно-ориентированном программировании полиморфизм подтипов (или полиморфизм включения) представляет собой концепцию в теории типов, предполагающую использование единого имени (идентификатора) при обращении к объектам нескольких разных классов, при условии, что все они являются подклассами одного общего надкласса (суперкласса). Полиморфизм подтипов состоит в том, что несколько типов формируют подмножество другого типа (их базового класса) и потому могут использоваться через общий интерфейс.

Պատմություն[խմբագրել | խմբագրել կոդը]

«Պոլիմորֆիզմ» տերմինը գալիս է հին հունական πολύς («շատ») և μορφή («ձև, տեսք») բառերից։ Տերմինն առաջին անգամ հիշատակվել է Քրիստոֆեր Սթրեչի «Ծրագրավորման լեզուների հիմնական հիմունքները» անվանումով լեկցիաների կոնսպեկտում։ Առաջին անգամ պոլիմորֆիզմը իրականացվել է ML լեզվում, ժառանգում և ինկապսուլյացիա հասկացողությունների հետ միասին։ Մի քանի տարի անց Common Lisp լեզվի Common Lisp Object System ենթաբազմությունը ստանդարտավորվեց՝ դառնալով օբյեկտային կողմնորոշված ծրագրավորման առաջին ստանդարտը։

Պոլիմորֆիզմի տեսակները[խմբագրել | խմբագրել կոդը]

Параметрический полиморфизм[խմբագրել | խմբագրել կոդը]

Կաղապար:См. также Параметрический полиморфизм позволяет определять функцию или тип данных обобщённо, чтобы значения могли обрабатываться идентично вне зависимости от их типа. Параметрический полиморфизм делает язык более выразительным, сохраняя полную статическую типобезопасность.

Параметрический полиморфизм повсеместно используется в функциональном программировании, где он обычно обозначается просто как «полиморфизм». Следующий пример демонстрирует параметризованный тип «список» и две опредёленные на нём параметрически полиморфные функции:

data List a = Nil | Cons a (List a)

length :: List a -> Integer
length Nil = 0
length (Cons x xs) = 1 + length xs

map :: (a -> b) -> List a -> List b
map f Nil = Nil
map f (Cons x xs) = Cons (f x) (map f xs)

Параметрический полиморфизм связывается с подтипизацией понятиями связанной квантификации и ковариантности/контравариантности (или полярности) конструкторов типов.

Концепция параметрического полиморфизма применима как к данным, так и к функциям. Функция, принимающая на входе или порождающая значения разных типов, называется полиморфной функцией. Тип данных, используемый как обобщённый (например, список элементов произвольного типа), называется полиморфным типом данных.

Параметрический полиморфизм также доступен в некоторых императивных (в частности, объектно-ориентированных) языках программирования, где для его обозначения обычно используется термин «обобщённое программирование»:

struct segment { int start; int end; };

int seg_cmpr( struct segment *a, struct segment *b )
{ return abs( a->end - a->start ) - abs( b->end - b->start ); }

int str_cmpr( char **a, char **b )
{ return strcmp( *a, *b ); }

struct segment segs[] = { {2,5}, {4,3}, {9,3}, {6,8} };
char* strs[] = { "three", "one", "two", "five", "four" };

main()
{
    qsort( strs, sizeof(strs)/sizeof(char*), sizeof(char*),
                 (int (*)(void*,void*))str_cmpr );

    qsort( segs, sizeof(segs)/sizeof(struct segment), sizeof(struct segment),
                 (int (*)(void*,void*))seg_cmpr );
    ...
}


template <typename T> T max(T x, T y)
{
    if (x < y)
        return y;
    else
        return x;
}

int main()
{
    int a = max(10,15);
    double f = max(123.11, 123.12);
    ...
}

В первом случае одна функция обрабатывает массивы элементов любого типа, для которого определена функция сравнения. Во втором случае определение функции на уровне исходного кода по-прежнему единственно, но в результате компиляции порождается такое количество перегруженных мономорфных функций, с каким количеством типов данных функция вызывается в программе (параметрический полиморфизм на уровне исходного кода транслируется в ad hoc полиморфизм на уровне целевой платформы).

Параметрически полиморфная функция использует аргументы на основе поведения, а не значения, апеллируя лишь к необходимым ей свойствам аргументов, что делает её применимой в любом контексте, где тип объекта удовлетворяет заданным требованиям поведения. Таким образом, реализуется концепция параметричности.

Ситуативный (ad hoc) полиморфизм[խմբագրել | խմբագրել կոդը]

Կաղապար:См. также

Кристофер Стрэчи избрал термин «ситуативный полиморфизм» для описания полиморфных функций, вызываемых для аргументов разных типов, но реализующих различное поведение в зависимости от типа аргумента (называемых также перегруженными функциями и перегруженными операторами). Термин «ad hoc» (лат. спонтанный, сделанный под текущую задачу) в этом смысле не несёт уничижительного подтекста — он означает лишь, что этот вид полиморфизма не является фундаментальным свойством системы типов языка. В следующем примере функции Add выглядят как реализующие один и тот же функционал над разными типами, но компилятор определяет их как две совершенно разные функции.

program Adhoc;

function Add( x, y : Integer ) : Integer;
begin
    Add := x + y
end;

function Add( s, t : String ) : String;
begin
    Add := Concat( s, t )
end;

begin
    Writeln(Add(1, 2));
    Writeln(Add('Hello, ', 'World!'));
end.

В динамически типизируемых языках ситуация может быть более сложной, так как выбор требуемой функции для вызова может быть осуществлён только во время исполнения программы.

Ситуативный полиморфизм иногда используется совместно с параметрическим. В языке Haskell стремление предоставить одновременно полиморфизм и перегрузку привело к необходимости введения принципиально нового понятия — классов типов (которые, вопреки распространённому заблуждению, не являются подмножеством объектно-ориентированной парадигмы программирования). С одной стороны, это позволяет существенно повысить выразительность программ, с другой чрезмерное их использование может приводить к сбоям механизма выведения типов, что вынуждает программистов отказываться от его использования, явно декларируя типы функций.

Полиморфизм подтипов (или полиморфизм включения)[խմբագրել | խմբագրել կոդը]

Կաղապար:См. также

Некоторые языки представляют идею подтипизации для ограничения спектра типов, применимых в определённом частном случае параметрического полиморфизма. В этих языках полиморфизм подтипов (обычно называемый также динамическим полиморфизмом) позволяет функции, определённой на типе T, также корректно исполняться для аргументов, принадлежащих типу S, являющемуся подтипом T (в соответствии с принципом подстановки Барбары Лисков). Такое отношение типов обычно записывается как S <: T. При этом тип T называется надтипом (или супертипом) для S, что обозначается как T :> S.

Например, если имеются типы Number, Rational и Integer, связанные отношениями Number :> Rational и Number :> Integer, то функция, определённая на типе Number, также сможет принять на вход аргументы типов Integer или Rational, и её поведение будет идентичным. Действительный тип объекта может быть скрыт как «чёрный ящик», и предоставляться лишь по запросу идентификации объекта. На самом деле, если тип Number является абстрактным, то конкретного объекта этого типа даже не может существовать (см. абстрактный тип данных, абстрактный класс). Данная иерархия типов известна — особенно в контексте языка Scheme — как числовая башня, и обычно содержит большее количество типов.

Объектно-ориентированные языки программирования реализуют полиморфизм подтипов посредством наследования, то есть определения подклассов. В большинстве реализаций каждый класс содержит т. н. виртуальную таблицу — таблицу функций, реализующих полиморфную часть интерфейса класса — и каждый объект (экземпляр класса) содержит указатель на виртуальную таблицу своего класса, по согласованию с которой производится вызов полиморфного метода. Такой механизм используется в случаях:

  • позднего связывания, где виртуальные функции не связаны до момента вызова;
  • одиночной диспетчеризации (то есть одноаргументного полиморфизма), где виртуальные функции связываются посредством простого просмотра виртуальной таблицы по первому аргументу (данному экземпляру класса), так что динамические типы остальных аргументов не учитываются.

То же применимо и к большинству остальных популярных объектных моделей. Некоторые, однако, такие как CLOS, предоставляют множественную диспетчеризацию, в которой метод полиморфен по всем аргументам.

В следующем примере коты и псы являются подтипами животных. Процедура определена для животных, но также будет работать корректно, получив на входе один из подтипов:

abstract class Animal {
    abstract String talk();
}
 
class Cat extends Animal {
    String talk() { return "Meow!"; }
}
 
class Dog extends Animal {
    String talk() { return "Woof!"; }
}
 

public class MyClass {
	 
    public static void write(Animal a) {
        System.out.println(a.talk());
    }
 
    public static void main(String args[]) {
        write(new Cat());
        write(new Dog());
    } 
}

Տես նաև[խմբագրել | խմբագրել կոդը]

Ծանոթագրություններ[խմբագրել | խմբագրել կոդը]

Կատեգորիա:Օբյեկտային կողմնորոշված ծրագրավորում