инкапсуляция, ad hoc полиморфизм и dynamic

356
24 апреля 2017, 01:29

Согласно ответу @Grundy на следующий вопрос :

2) Почему в нижеприведённом примере,в foreach при использовании var - нет доступа к Key и Value,а при использовании dynamic - есть?

оригинал вопроса:Различие между использованием var и dynamic в foreach

class UserCollection
{
    public static IEnumerable Generator()
    {
        yield return new { Key = 0, Value = "Zero" };
        yield return new { Key = 1, Value = "One" };
        yield return new { Key = 2, Value = "Two" };
    }
}
class Program
{
    static void Main()
    {
        foreach (var item in UserCollection.Generator())
        {               
            Console.WriteLine("Key = {0}, Value = {1}", item.Key, item.Value);               
        }
        // Delay.
        Console.ReadKey();
    }
}

С dynamic это работает потому, что проверка на существование свойств происходит не во время компиляции, а во время выполнения, так как реально возвращается объект с нужными полями, ошибки не возникает.

И затрагивая вот эту тему: Согласно ответу @VladD на следующий вопрос :

Метод с dynamic внутри — ещё один валидный пример параметрического полиморфизма. (Но не ad hoc, по идее.) Хотя, вызов правильного метода при использовании f((dynamic)o) — это снова ad hoc-полиморфизм.

-вот почему в заголовке вопроса я упоминаю ad hoc полиморфизм

Оригинал Вопроса:

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

Вот в чем заключается мой вопрос:

Как я понял, ad hoc полиморфизм заключается в том, что именно благодаря времени проверки - и не происходит инкапсуляция?

я спрашиваю о том, почему именно не происходит инкапсуляция - она не происходит из за времени проверки? т.е инкапсуляция не происходит из за того что проверка типов выполняется во время выполнения?

И именно поэтому это все можно назвать ad hoc полиморфизмом?

P.s Но это не как не вопрос про разницу ad hoc и обычного полиморфизма - здесь я просто привел ссылку на этот вопрос в качестве первоисточника, откуда затрагивается тема ad hoc полиморфизма.

Answer 1

Смотрите. В вашем вопросе есть несколько неверных утверждений. Давайте попробуем пройтись по ним.

Как я понял, ad hoc полиморфизм заключается в том, что именно благодаря времени проверки - и не происходит инкапсуляция?

Смотрите, инкапсуляция — это свойство языка держать данные и методы для работы с ними в одном общем месте (именуемом обычно «класс»). То, что при этом некоторые данные доступны для использования снаружи класса, а некоторые нет, не есть составной частью полиморфизма. Это называется «сокрытие данных/методов». Хотя английская википедия рассматривает оба определения: в котором сокрытие считается частью инкапсуляции, и в котором это отдельная концепция.

Давайте, чтобы не создавать недоразумения, говорить о сокрытии данных/методов.

Далее, важная часть. Механизмом сокрытия данных является объявление их как private/public. То, что вы не знаете реальный тип объекта, не является сокрытием данных.

Пример:

class Test
{
    public int X;
    private int Y;
}

Пускай у нас есть такие переменные:

var     v1 = new Test();
object  v2 = new Test();
var     v3 = (object)(new Test());
object  v4 = (object)(new Test());
dynamic v5 = new Test();
dynamic v6 = (object)(new Test());

Какой тип этих переменных? Этот вопрос делится на два вопроса: compile-time (заявленный) тип и run-time (фактический) тип.

Фактический тип каждой из переменных — Test. Заявленный тип v1Test, v2, v3 и v4object, v5 и v6dynamic.

У переменной v1 вы можете получить доступ к полю X и не можете к полю Y именно вследствие работы сокрытия данных: это private-поле.

У переменных v2, v3 и v4 вы не можете получить доступ к полю X не из-за сокрытия данных, а из-за того, что вы не видите на этапе компиляции её фактический тип. Но вы можете получить этот доступ, выполнив преобразование типов:

((Test)v2).X = 1;

Доступ к полю Y вы не можете получить даже при преобразовании типов.

С переменными v5 и v6 тоже всё просто. Они ведут себя во время выполнения так, как будто бы заявленный тип совпадает с фактическим. То есть снова-таки вы можете получить доступ к полю X, но не к полю Y.

Таким образом, мы видим, что сокрытие данных (то есть, возможность получить доступ к X и невозможность к Y) работает всегда, независимо от полиморфных средств языка.

я спрашиваю о том, почему именно не происходит инкапсуляция - она не происходит из за времени проверки? т.е инкапсуляция не происходит из за того что проверка типов выполняется во время выполнения?

Сокрытие данных, как вы видели, происходит, в любом случае. Проверка типов во время выполнения для dynamic лишь делает преобразование к нужному типу за вас, но не открывает доступ к закрытым данным.

READ ALSO
Структура программы

Структура программы

Как выглядит схема взаимосвязи модулей программы? Нужно нарисовать структуру программы, состоящей из 3 модулейА как она выглядит - не представляю

277
Модернизация метода Replace() для строки

Модернизация метода Replace() для строки

есть строка с текстом вида "D15 D7 B12 String

255
Вычесление скорости загрузки файла cSharp WebClient

Вычесление скорости загрузки файла cSharp WebClient

Как измерить скорость загрузки файла при использовании webClientDownloadFileTaskAsync? Предчувствую сильную зависимость вычислений от загруженности...

281
Прокрутка слайдера WPF. XAML Binding С#

Прокрутка слайдера WPF. XAML Binding С#

Привязываю значение слайдера к позиции видео в медиаэлементеКак бы привязка верно сделана но не работате

437