Страницы

Поиск по вопросам

пятница, 13 декабря 2019 г.

Чем ad hoc полиморфизм отличается от обычного полиморфизма?

#c_sharp


Как я понимаю в C# полиморфизм заключается в использовании виртуальных членов и в
приведении типов, но наткнулся еще на упоминание ad hoc полиморфизма, и никак не могу
понять чем же он отличается от использования виртуальных членов?
    


Ответы

Ответ 1



Насколько я понимаю, ad hoc-полиморфизм — это полиморфизм, основанный на различении типов. Для различных типов аргументов используется разный код функции. Один классический пример — это перегрузка (overloading) метода: class C { public void f(int x) { Console.WriteLine("C.f(int)"); } public void f(string x) { Console.WriteLine("C.f(string)"); } } Здесь имя f привязано к двум различным методам, и компилятор выбирает тот или иной метод в зависимости от типа аргумента. Это пример статического ad hoc-полиморфизма: типы должны быть известны на этапе компиляции, и компилятор точно знает, который из методов будет выполнен. Другой пример ad hoc-полиморфизма — это переопределение (overriding) виртуального метода: class B { public virtual void f(int x) { Console.WriteLine("B.f(int)"); } } class D : B { public override void f(int x) { Console.WriteLine("D.f(int)"); } } Здесь также происходит различение по типам, но на этот раз — по типу неявного нулевого аргумента this. Выбор переопределённого метода откладывается на момент выполнения; на момент компиляции компилятор точно не знает, какой из группы переопределённых методов будет выполнен. Это пример динамического ad hoc-полиморфизма. Кроме того, есть ещё понятие параметрического полиморфизма: это ситуация, когда один и тот же метод работает с аргументами различных типов одинаково, не зависимо от их точного типа. Тривиальный пример для языков с наследованием (например, C#) — функция, работающая с объектом некоторого класса C, часто может без изменений работать с объектом порождённого от C класса (этот вид полиморфизма часто называют полиморфизм включения). Менее тривиальный пример — generic-методы, которые могут, в зависимости от generic-параметра, работать с разными типами объектов. Пример: class Enumerable { public T First(this IEnumerable seq) { using (IEnumerator en = seq.GetEnumerator()) { if (!en.MoveNext()) throw new InvalidOperationException(); return en.Current; } } }

Ответ 2



Есть 3 основных вида полиморфизма (покажу на примере php, c# не знаю): Ad hoc полиморфизм — несколько объявлений функции с одинаковым именем но с отличающимися параметрами, пример: При вызове функции выберется та которой соответствует тип аргумента. function test (string $a, string $b) { return $a . $b; } function test (int $a, int $b) { return $a + $b; } // если бы в пхп поддерживалось, то вывело бы test('a', 'b') // 'ab' test(1, 4) // 5 Параметрический полиморфизм — когда будет выполнятся одна и та же функция вне зависимости от типов аргументов. В php он поддерживается. function test (string $a, string $b) { return $a . $b; } function test (int $a, int $b) { return $a + $b; } // если бы в пхп поддерживалось, то вывело бы test('a', 'b') // 'ab' test(1, 4) // 5 Параметрический полиморфизм является истинной формой полиморфизма, делая язык более выразительным и существенно повышая коэффициент повторного использования кода. Традиционно ему противопоставляется Ad hoc полиморфизм (мнимая форма). Subtype полиморфизм — насколько понял это самое популярное понятие полиморфизма. Это возможность объектов с одинаковой спецификацией иметь различную реализацию. Например, есть интерфейс LoggerInterface, это как спецификация. Если есть классы которые имплементируют этот интерфейс, например, класс FileLogger и DBLogger, то это называется полиморфизмом. interface LoggerInterface { public function log($logs); } class FileLogger implements LoggerInterface { public function log($logs) { // записывает логи в файл } } class DBLogger implements LoggerInterface { public function log($logs) { // записывает логи в БД } } Вместо интерфейса может быть наследование через абстрактный (виртуальный) класс или даже обычный класс. То есть когда есть методы в разных классах которые делают то же самое, им можно дать одинаковое имя и сделать чтобы эти классы реализовывали единый интерфейс или наследовали единый абстрактный класс с этим абстрактным методом.

Комментариев нет:

Отправить комментарий