Динамические свойства языка программирования как преимущество — objective-c теория связывание-данных

1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд
Загрузка...

Вопрос:


Наверстываю упущенную теорию по парадигмам языков программирования.

В обучающих материалах по ObjC часто встречается восхищение динамичностью языка (динамическое связывание, динамическая типизация…) с указанием на то что многое можно делать в рантайме плюс описание соответствующих трюков. Читая документ со страницы 23 я понимаю что это есть свойство языка, но не преимущество. Предполагаю, что сравнивая со статически типизированными языками все те же трюки выполняются в них с тем же успехом, но не в runtime a в compile-time. Раздел статьи Преимущества (равно как и другие статьи в сети) свет на вопрос для меня не пролил и не дал понять в чем именно преимущество а не просто отличие от парадигмы статической типизации. Прошу просветить и указать в чем именно преимущество динамической типизации над статической.

UPDATE:
Если будут получены объемные ответы на вопрос о природе явления в целом, то с целью оставить тред потомкам я добавлю метки всех языков соответствующих парадигме и уберу акцент на objc из топика.

UPDATE 2:
Получены прекрасные всеобъемлющие ответы, в частности от @VladD. C целью аккумулирования топиком общеобразовательной ценности хотелось бы читать мнение и других участников форума. Заранее благодарен за передачу опыта и знаний!

Автор вопроса: AlexThumb

VladD

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

Итак, что такое «динамическая система типов»? Определения в источниках наподобие Википедии говорят, что разница в том, присваивается ли тип переменной при объявлении (и остаётся ли таким навсегда) либо при присваивании (и меняется с каждым следующим присваиванием). Это, однако, слишком грубое описание существующего положения вещей. Куда честнее и точнее было бы говорить о богатстве системы типов, и о том, насколько полно она отображает семантику предметной области.

Крайний пример — языки типа большинства ассемблеров, в которых существует лишь один тип — числовой. Это соответствует примерам «максимально динамической» системы типов: переменная может содержать число, указатель, структуру из двух байт и т. д.

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

На деле же все языки стоят где-то посередине между этими двумя крайностями. Языки, которые считаются «динамически типизированными» или «слабо типизированными» (в зависимости от того, одобряет или осуждает программист это явление), имеют меньшее количество типов, и операции между значениями с разной семантикой либо завершаются с ошибкой, либо приводят к бессмысленному результату.

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

Языки наподобие C++ предоставляют более богатую систему типов: вы, например, не сможете «вызвать функцию» по переменной типа int. Таким образом, у операций в C++ гораздо меньше возможностей завершиться аварийно из-за несоответствия типов. Тем не менее, язык предоставляет вам возможность нарушить защиту: оператор приведения типов. Вы можете привести тип строки к типу числа, и попытаться выполнить числовую операцию с полученным значением. Согласно стандарту языка, вы получите неопределённое поведение, то есть, что угодно имеет право произойти. Кроме того, определённые черты слабо типизированных языков есть и в C++: операция сложения между различными арифметическими типами вызывает неявную конверсию операндов к наиболее общему типу.

Язык наподобие C# мог бы казаться ещё более статически типизированным (в нём нету аналога reinterpret_cast, и тип проверяется всегда), но зато в нём есть ключевое слово dynamic, близкое по идеологии к eval. Из особенностей динамических языков, перечисленных в Википедии, C# обладает в той или иной степени всеми, за исключением, пожалуй, макросов.

Где-то посередине по богатству системы типов стоит SQL: в нём есть набор примитивных типов, но нет возможности расширить систему типов, применимо к нуждам пользователя.


Итак, под динамической системой типов обычно понимается система типов, в которой меньше базовых типов, и/или некоторые операции могут применяться к разным типам с возможностью получения ошибки времени выполнения либо малоосмысленного результата. Большинство языков обладают этим свойством в той или иной мере.

Литература для дальнейшего чтения: [1], [2], [3], [4].


Преимущества «более динамических» языков:

  • Лучшая выразительность в некоторых сценариях, например, там где программист хочет сказать «я уверен, что этот объект умеет выполнить эту операцию» или «объекты, не умеющие делать это, игнорируются». Для сильнее типизированных языков такая семантика достигается использованием приведения типов или другой разновидностью проверки времени выполнения. Например, в Objective C, насколько я знаю, можно отправить произвольное сообщение произвольному объекту (разновидность duck typing); в C# для этого нужно, чтобы объект поддерживал соответствующий интерфейс, или использование dynamic, то есть откладывание проверки до момента выполнения.
  • Неявная, «плавающая» семантика объектов по сравнению с явно заданными, продуманными и жёстко прописанными типами позволяет легко менять смысл классов и операций при разработке. (Не могу придумать пример для Objective C.) Это увеличивает скорость прототипирования, хотя, возможно, и негативно скажется на качестве кода при длительной разработке проекта. Отсюда распространённое мнение о том, что «динамические» языки лучше подходят для построения proof of concept, а статические — для имплементации.
  • Более удобное общение с популярными нетипизированными или слаботипизированными структурами, такими как XML- и JSON-документы.
  • Ещё один часто забываемый пример динамического свойства языков: виртуальные функции.
  • Преимуществом более динамических языков является более простая диспетчеризация вызовов функций: если у меня определены f(Base, Base), f(Base, Derived), f(Derived, Base) f(Derived, Derived), язык с развитой динамической типизацией сможет автоматически выбрать нужную перегрузку при вызове метода, в то время как другие языки вынуждены пользоваться паттерном наподобие Visitor. Частным случаем диспетчеризации по одному, нулевому аргументу является вызов виртуальной функции.
  • Некоторые языки умеют управлять кодом во время выполнения. Например, в Javascript’е можно переопределить любой метод через прототип, в Objective C можно подменить класс, используя категории (если я не ошибаюсь), в Питоне можно модифицировать поведение методов при помощи аннотаций. Достижение подобных эффектов в не приспособленных для этого языках сопряжено со значительным объёмом кода и нередко требует от пользователей неестественного, неудобного или даже опасного синтаксиса. (Например, оборачивать каждое объявление поля в макрос.)

Суммируя: для понятий, встроенных в систему типов, динамически типизированные языки проигрывают статически типизированным в выразительной силе (пример: в статическом языке легко запретить складывать длину с весом, а в динамическом — нет). Для понятий, не описываемых системой типов, динамические языки выразительнее (пример всем объектам с полем возраст увеличить этот самый возраст на 1: в статических языках требует интерфейса, одинакового имени свойства и одинакового типа свойства).


Многие преимущества, которые традиционно считаются преимуществами динамических языков, на самом деле лишь следствия хорошо организованной среды выполнения (рантайма), и в частности не требуют интерпретации или виртуальной машины. Например, интроспекция/рефлексия есть не вопрос динамичности, а лишь вопрос доступности метаданных во время выполнения, и вполне статичная с точки зрения системы типов Java её реализует. Замыкания, которые в Javascript’е есть чисто динамическая особенность, реализуются статически с полным контролем типизации в Objective C (под именем блоков) и C#. Английская Википедия считает, что динамические черты

… can be emulated in nearly any language of sufficient complexity, but dynamic languages provide direct tools to make use of them.

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

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

Преимущества

  • Минимум дополнительных строк: переменные надо либо просто объявить без указания типа (JavaScript), либо вообще объявлять не нужно (Бейсик) или не обязательно (PHP).
  • Соответственно, упрощается написание простых программ
  • Повышается гибкость языка. Например, только динамический язык может иметь функцию eval(), вычисляющую значение произвольного выражения.
  • Ускоряет работу компилятора — а значит, производственный цикл «написать-проверить».
  • Автоматически даёт языку элементы метапрограммирования и интроспекции.
  • Упрощается работа прикладного программиста с СУБД, которые принципиально возвращают информацию в «динамически типизированном» виде. Поэтому динамические языки ценны, например, для программирования веб-служб.
  • Иногда требуется работать с данными переменного типа. Например, функция поиска подстроки возвращает позицию найденного символа (число) или маркер «не найдено». В PHP этот маркер — булевское false. В статических языках это особая константа (0 в Паскале, std::string::npos в C++).
    Динамическая типизация Википедия

Источник

Вам также может быть интересно:

Использование вложенных маршрутов в React Router — javascript reactjs react-router
Вопрос: Для организации маршрутов в приложении использую React Router. <Route path="/" component={...}> <IndexRoute component={...}/> <Route path="user/:userId" component={...}> ...
Как с помощью Retrofit 2.0 отправить данные в JSON на сервер и получить ответ? — java android retrofit
Вопрос: Только начал читать про Retrofit 2.0 до этого использовал HttpURLConnection. Как я работаю с HttpURLConnection, формирую Json перевожу его в byte, ставлю header в ...
Не приходят push уведомления. FCM — android firebase android-notification
Вопрос: Появилась необходимость реализовать push уведомления. Прописал в манифесте сервис: <service android:name=".MyFirebaseMessagingService"> <intent-filter> ...
Принцип браузерной игры в линукс терминале — java linux terminal
Вопрос: Наткнулся на Java библиотеку CHARVA. И хотел бы уточнить у знающих людей, возможно ли на основе данной библиотеки сделать программу по принципу браузерной игры, но ...
Мерцание заблокированного экрана при выключенной подсветке в Debian 8 Gnome 3 — linux debian экран
Вопрос: На ноутбуке с Debian 8 Jessie и Gnome 3 имеется следующая проблема. При выключенном заблокированном экране сквозь него можно наблюдать, как весь экран становится белым, ...
Создание WCF клиента на готовый SOAP web сервер — c# wcf
Вопрос: Доброго времени суток. Появилась задача опрашивать web сервер с клиента на котором планируется написать WCF клиентскую часть. Информации про сервер очень мало (не знаю платформу ...
Безопасно ли удалить файл логов general_log.txt? — mysql
Вопрос: При выполнении запроса со вставкой данных большого объёма SQLyog начал вылетать с ошибкой: not enough memory application terminated В связи с этим я решила ...
Callback функции создания таблицы mysql в nodejs — mysql node.js callback
Вопрос: Есть функция, которая при запуске создает базу даных, function showDb() { pool.query("show databases like 'bt' ",function (err, ...
Как создать Adapter с неограниченным количеством строк и с неограниченным разным количеством столбцов в каждой строке — java android
Вопрос: Как создать Adapter с неограниченным количеством строк и с неограниченным разным количеством столбцов в каждой строке Автор вопроса: Salut Amigo Источник
Не могу передать байтовый массив в контроллер — c# asp.net-mvc entity-framework
Вопрос: У меня изображения храняться в бд в формате байтового массива, через форич отлично все выводит, но когда я хочу открыть страницу для работы с ...
proguard release error — java android mvp
Вопрос: Включил в проекте proguard, apk собирается, все хорошо, но приложение не работает) Proguard-rules.pro -keepattributes InnerClasses -keepattributes EnclosingMethod -keepattributes *Annotation* -dontoptimize # Keep Butterknife -keep class butterknife.** { *; } -dontwarn butterknife.internal.** -keep ...
Не отрабатывает page:update — javascript ruby-on-rails
Вопрос: Есть мой учебный проект на ruby. Делаю редактирование объектов с помощью JS. Сейчас работает так: Редактирую первый раз - всё нормально. Не обновляя страницу, ...
Как найти определенный символ в строке и удалить значение после него (и вместе с ним) Jquery — javascript html jquery
Вопрос: Здравствуйте, есть определенный набор строк, типа "L / Красный / 12345", как можно на странице найти их, и вырезать из них все что находится ...
Почему не работает wildcard module declaration? — typescript
Вопрос: Почему не работает такой способ декларации: declare module "*!text" {} ? Цель - использовать контент файла в переменной: import layout = require("/js/views/layouts/wnd.html!text"); или так: import layout from "/js/views/layouts/wnd.html!text"; Если ...
Как прервать 3rd-party код? — c# многопоточность .net-core
Вопрос: Есть 3rd-party код из библиотеки который "зависает" в ожидании где-то в работе с сетью. CancellationToken поддержки нет, таймаутов нет. Запускаю я его через: Task.Run(() => ...

Оставьте ответ

Ваш e-mail не будет опубликован. Обязательные поля помечены *