stringtranslate.com

Эйфель (язык программирования)

Eiffel — это объектно-ориентированный язык программирования , разработанный Бертраном Мейером (сторонником объектно-ориентированной ориентации и автором книги « Объектно-ориентированное создание программного обеспечения ») и Eiffel Software. Мейер придумал этот язык в 1985 году с целью повышения надежности разработки коммерческого программного обеспечения; [4] первая версия стала доступной в 1986 году. В 2005 году Eiffel стал языком, стандартизированным ISO .

Конструкция языка тесно связана с методом программирования Эйфеля. Оба основаны на наборе принципов, включая проектирование по контракту , разделение команд и запросов , принцип единообразного доступа , принцип единственного выбора , принцип открытия-закрытия и разделение опций и операндов .

Многие концепции, первоначально представленные Эйфелем, позже нашли свое применение в Java , C# и других языках. [5] Новые идеи дизайна языка, особенно благодаря процессу стандартизации Ecma / ISO , продолжают включаться в язык Eiffel.

Характеристики

Ключевые характеристики языка Эйфеля включают в себя:

Цели дизайна

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

Эйфель избегает приемов кодирования или методов кодирования, предназначенных для подсказки компилятору по оптимизации . Цель состоит не только в том, чтобы сделать код более читабельным, но и в том, чтобы позволить программистам сконцентрироваться на важных аспектах программы, не увязая в деталях реализации. Простота Эйфеля призвана способствовать простым, расширяемым, многоразовым и надежным решениям вычислительных задач. Компиляторы компьютерных программ, написанных на Eiffel, предоставляют обширные методы оптимизации, такие как автоматическое встраивание, которые освобождают программиста от части бремени оптимизации.

Фон

Eiffel изначально был разработан Eiffel Software, компанией, основанной Бертраном Мейером . «Объектно-ориентированное построение программного обеспечения» содержит подробное рассмотрение концепций и теории объектной технологии, которые привели к созданию Эйфеля. [9]

Целью разработки языка Eiffel, библиотек и методов программирования является предоставление программистам возможности создавать надежные программные модули многократного использования. Eiffel поддерживает множественное наследование , универсальность , полиморфизм , инкапсуляцию , типобезопасные преобразования и ковариацию параметров . Самый важный вклад Эйфеля в разработку программного обеспечения — это проектирование по контракту (DbC), в котором утверждения , предусловия , постусловия и инварианты классов используются, чтобы помочь гарантировать корректность программы без ущерба для эффективности.

Дизайн Эйфеля основан на теории объектно-ориентированного программирования с незначительным влиянием других парадигм или заботой о поддержке устаревшего кода. Eiffel формально поддерживает абстрактные типы данных . По замыслу Эйфеля, текст программного обеспечения должен иметь возможность воспроизводить проектную документацию из самого текста, используя формализованную реализацию «абстрактного типа данных».

Реализации и среды

EiffelStudio — это интегрированная среда разработки , доступная по лицензии с открытым исходным кодом или по коммерческой лицензии. Он предлагает объектно-ориентированную среду для разработки программного обеспечения . EiffelEnvision — это плагин для Microsoft Visual Studio , который позволяет пользователям редактировать, компилировать и отлаживать проекты Eiffel из интегрированной среды разработки Microsoft Visual Studio. Доступны еще пять реализаций с открытым исходным кодом : «Эйфелев компилятор» tecomp; Гобо Эйфелев; SmartEiffel , реализация GNU, основанная на более старой версии языка; LibertyEiffel , основанный на компиляторе SmartEiffel; и Визуальная Эйфелева .

Некоторые другие языки программирования включают элементы, впервые представленные в Eiffel. Например, Sather изначально был основан на Eiffel, но с тех пор разошелся и теперь включает в себя несколько функций функционального программирования . Язык интерактивного обучения Blue, предшественник BlueJ , также основан на Eiffel. Apple Media Tool включает язык Apple Media Language на основе Eiffel.

Технические характеристики и стандарты

Определение языка Эйфеля является международным стандартом ISO . Стандарт был разработан ECMA International , которая впервые утвердила его 21 июня 2005 года как Стандарт ECMA-367, Eiffel: Язык анализа, проектирования и программирования. В июне 2006 года ECMA и ISO приняли вторую версию. В ноябре 2006 года ISO впервые опубликовала эту версию. Стандарт можно найти и бесплатно использовать на сайте ECMA. [10] Версия ISO [11] идентична во всех отношениях, кроме форматирования.

Eiffel Software, tecomp «The Eiffel Compiler» и Gobo, разработчик библиотек Eiffel, взяли на себя обязательство реализовать этот стандарт; EiffelStudio 6.1 и tecomp «The Eiffel Compiler» от Eiffel Software реализуют некоторые из основных новых механизмов, в частности, встроенные агенты, команды присваивания, обозначение скобок, несоответствующее наследование и присоединенные типы. Команда SmartEiffel отошла от этого стандарта, чтобы создать свою собственную версию языка, которая, по их мнению, ближе к оригинальному стилю Eiffel. Object Tools не сообщила, будут ли будущие версии компилятора Eiffel соответствовать этому стандарту. LibertyEiffel реализует диалект где-то между языком SmartEiffel и стандартом.

В стандарте приводятся следующие спецификации предшествующего языка Эйфеля:

Текущая версия стандарта от июня 2006 года содержит некоторые несоответствия (например, ковариантные переопределения ) . Комитет ECMA еще не объявил никаких сроков и указаний по устранению несоответствий.

Синтаксис и семантика

Общая структура

Эйфелева «система» или «программа» представляет собой набор классов . Выше уровня классов Эйфель определяет кластер , который по сути представляет собой группу классов и, возможно, подкластеров (вложенных кластеров). Кластеры — это не синтаксическая языковая конструкция , а скорее стандартное организационное соглашение. Обычно программа Eiffel организуется так, что каждый класс хранится в отдельном файле, а каждый кластер — в каталоге, содержащем файлы классов. В этой организации подкластеры представляют собой подкаталоги. Например, согласно стандартным организационным соглашениям и соглашениям о регистре, x.eэто может быть имя файла, определяющего класс с именем X.

Класс содержит функции , похожие на «подпрограммы», «члены», «атрибуты» или «методы» в других объектно-ориентированных языках программирования. Класс также определяет свои инварианты и содержит другие свойства, такие как раздел «примечания» для документации и метаданных. Стандартные типы данных Эйфеля, такие как INTEGER, STRINGи ARRAY, сами по себе являются классами.

В каждой системе должен быть класс, обозначенный как «корневой», и одна из процедур его создания, обозначенная как «корневая процедура». Выполнение системы состоит из создания экземпляра корневого класса и выполнения его корневой процедуры. Обычно при этом создаются новые объекты, вызываются новые функции и т. д.

У Эйфеля есть пять основных исполняемых инструкций: присваивание, создание объекта, вызов подпрограммы, условие и итерация. Структуры управления Эйфеля строги в обеспечении структурного программирования : каждый блок имеет ровно один вход и ровно один выход.

Обзор

В отличие от многих объектно-ориентированных языков, как и Smalltalk , Eiffel не допускает каких-либо присвоений атрибутам объектов, за исключением свойств объекта, что является практическим применением принципа сокрытия информации или абстракции данных, требующего формальных интерфейсов для данных. мутация. Говоря языком других объектно-ориентированных языков программирования, все атрибуты Eiffel «защищены», а для клиентских объектов необходимы «установщики» для изменения значений. Результатом этого является то, что «сеттеры» могут и обычно реализуют инварианты, для которых Eiffel предоставляет синтаксис.

Хотя Eiffel не разрешает прямой доступ к функциям класса клиенту класса, он позволяет определить «команду присваивателя», например:

  some_attribute : SOME_TYPE присваивает set_some_attribute set_some_attribute ( v : VALUE_TYPE ) — Устанавливает значение some_attribute в `v'. сделать some_attribute := v end             

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

В отличие от других языков, имеющих понятия «публичный», «защищенный», «частный» и т. д., Eiffel использует технологию экспорта для более точного управления областью действия между классами клиента и поставщика. Видимость функции проверяется статически во время компиляции. Например, (ниже) «{NONE}» аналогично слову «protected» на других языках. Область применения, примененная таким образом к «набору функций» (например, все, что находится ниже ключевого слова «функция» до следующего ключевого слова набора функций или конца класса), может быть изменена в классах-потомках с помощью ключевого слова «экспорт».

Feature { NONE } -- Инициализация default_create -- Инициализировать новый нулевой десятичный экземпляр. сделайте make_zero end  

Альтернативно, отсутствие декларации экспорта {x} подразумевает {ANY} и аналогично «публичной» области действия других языков.

функция -- Константы 

Наконец, область видимости можно избирательно и точно контролировать для любого класса во вселенной проекта Eiffel, например:

функция { DECIMAL , DCM_MA_DECIMAL_PARSER , DCM_MA_DECIMAL_HANDLER } -- Доступ    

Здесь компилятор разрешит доступ к функциям внутри группы функций только классам, перечисленным в фигурных скобках (например, DECIMAL, DCM_MA_DECIMAL_PARSER, DCM_MA_DECIMAL_HANDLER ).

"Привет, мир!"

Внешний вид языка программирования часто передается с помощью фразы «Hello, world!» программа. Такая программа, написанная на Eiffel, может быть:

класс HELLO_WORLD create make Feature make do print ( "Hello, world!%N" ) end end       

Эта программа содержит класс HELLO_WORLD. Конструктор (программа создания) класса с именем makeвызывает printпроцедуру системной библиотеки для записи "Hello, world!"сообщения на выход.

Проектирование по договору

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

Компилятор Eiffel предназначен для включения контрактов функций и классов на различных уровнях. Например, EiffelStudio выполняет все контракты функций и классов во время выполнения в «режиме рабочей среды». Когда создается исполняемый файл, компилятор через файл настроек проекта (например, файл ECF) получает указание включить или исключить любой набор контрактов. Таким образом, исполняемый файл может быть скомпилирован так, чтобы включать или исключать любой уровень контракта, тем самым обеспечивая непрерывные уровни модульного и интеграционного тестирования. Более того, контракты можно постоянно и методично выполнять с помощью функции автотестирования, доступной в EiffelStudio.

Механизмы проектирования по контракту тесно интегрированы с языком и позволяют переопределить функции наследования:

Кроме того, язык поддерживает «инструкцию проверки» (разновидность «утверждения»), инварианты цикла и варианты цикла (гарантирующие завершение цикла).

Безопасная способность

Функция Void-safe, такая как статическая типизация, является еще одним средством улучшения качества программного обеспечения. Программное обеспечение, безопасное для Void, защищено от ошибок во время выполнения, вызванных вызовами ссылок void , и, следовательно, будет более надежным, чем программное обеспечение, в котором могут происходить вызовы целей void. Аналогия со статической типизацией полезна. Фактически, возможность void-безопасности можно рассматривать как расширение системы типов или шаг за пределы статической типизации, поскольку механизм обеспечения void-безопасности интегрирован в систему типов.

Защиту от вызовов void target можно увидеть с помощью понятия прикрепления и (расширенного) отсоединения (например, ключевого слова detachable). Функцию void-safe можно увидеть в короткой переработке примера кода, использованного выше:

 some_attribute : съемный SOME_TYPE use_some_attribute — Установить значение some_attribute в `v'. do, если прикрепил some_attribute как l_attribute then do_something ( l_attribute ) end end do_something ( a_value : SOME_TYPE ) -- Сделайте что-нибудь с `a_value'. сделать ... сделать что-нибудь с ` a_value ' ... конец                             

В приведенном выше примере кода показано, как компилятор может статически определять надежность some_attributeподключения или отсоединения в момент использования. Примечательно, что attachedключевое слово допускает «локальное вложение» (например, l_attribute), которое ограничивается только блоком кода, заключенным в конструкцию if-statement. Таким образом, в этом небольшом блоке кода l_attributeможно статически гарантировать, что локальная переменная (например, ) непустая (т.е. недействительная).

Возможности: команды и запросы.

Основная характеристика класса заключается в том, что он определяет набор функций: поскольку класс представляет собой набор объектов времени выполнения или «экземпляров», функция представляет собой операцию над этими объектами. Существует два типа функций: запросы и команды. Запрос предоставляет информацию об экземпляре. Команда изменяет экземпляр.

Различие между командой и запросом важно для метода Эйфеля. В частности:

Перегрузка

Eiffel не допускает перегрузку аргументов . Каждое имя объекта внутри класса всегда соответствует определенному объекту внутри класса. Одно имя в одном классе означает одно. Такой выбор дизайна способствует читабельности классов, избегая двусмысленности относительно того, какая подпрограмма будет вызываться при вызове. Это также упрощает языковой механизм; в частности, именно это делает возможным механизм множественного наследования Эйфеля. [12]

Имена, конечно, можно повторно использовать в разных классах. Например, функция plus (вместе с ее инфиксным псевдонимом «+» ) определена в нескольких классах: INTEGER , REAL , STRING и т. д.

родство

Общий класс — это класс, который варьируется в зависимости от типа (например, СПИСОК [ТЕЛЕФОН], список телефонных номеров; АККАУНТ [G->АККАУНТ_ТИП], позволяющий АККАУНТ [ЭКОНОМИЯ] и АККАУНТ [ПРОВЕРКА] и т. д.). Классы могут быть универсальными, чтобы выразить их параметризацию по типам. Общие параметры отображаются в квадратных скобках:

класс СПИСОК [ G ] ...   

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

предмет : G do ... end put ( x : G ) do ... end         

И являются «общими производными» этого класса LIST [INTEGER]. LIST [WORD]Разрешенные комбинации (с n: INTEGER, w: WORD, il: LIST [INTEGER], wl: LIST [WORD]):

п := ил . товар вл . положить ( ш )   

INTEGERи WORDявляются «фактическими родовыми параметрами» в этих родовых выводах.

Также возможно иметь «ограниченные» формальные параметры, для которых фактический параметр должен наследовать от данного класса, «ограничения». Например, в

 класс HASH_TABLE [ G , KEY -> HASHABLE ]     

вывод HASH_TABLE [INTEGER, STRING]действителен только в том случае, если STRINGон наследуется от HASHABLE(как это действительно происходит в типичных библиотеках Eiffel). Внутри класса, имея KEYограничения HASHABLEсредствами, которые x: KEYможно применить ко xвсем функциям HASHABLE, как в x.hash_code.

Основы наследования

Чтобы наследовать от одного или нескольких других, класс должен включать inheritпредложение в начале:

класс C наследует A B    -- ... Остальная часть объявления класса...

Класс может переопределить (переопределить) некоторые или все унаследованные функции. Это должно быть явно объявлено в начале класса через redefineподпункт предложения о наследовании, как в

класс C наследует A переопределить f , g , h end B переопределить u , v end             

См. [13] для полного обсуждения наследования Эйфеля.

Отложенные классы и функции

Классы могут быть определены с помощью, deferred classа не с class, чтобы указать, что класс не может быть создан напрямую. Несоздаваемые экземпляры классы называются абстрактными классами в некоторых других объектно-ориентированных языках программирования. На языке Эйфеля можно создать экземпляр только «эффективного» класса (он может быть потомком отложенного класса). Функцию также можно отложить, используя deferredключевое слово вместо предложения do. Если класс имеет какие-либо отложенные функции, он должен быть объявлен как отложенный; однако класс без отложенных функций, тем не менее, сам может быть отложен.

Отложенные классы играют отчасти ту же роль, что и интерфейсы в таких языках, как Java, хотя многие теоретики объектно-ориентированного программирования полагают, что сами интерфейсы во многом являются ответом на отсутствие в Java множественного наследования (которое есть у Эйфеля). [14] [15]

Переименование

Класс, который наследуется от одного или нескольких других, получает все свои функции по умолчанию под их первоначальными именами. Однако он может изменить их названия посредством renameпунктов. Это требуется в случае множественного наследования, если между унаследованными функциями возникают конфликты имен; без переименования полученный класс нарушит указанный выше принцип отсутствия перегрузки и, следовательно, будет недействительным.

Кортежи

Типы кортежей можно рассматривать как простую форму класса, предоставляющую только атрибуты и соответствующую процедуру установки. Типичный тип кортежа читается

 КОРПУС [ имя : СТРОКА ; вес : РЕАЛЬНЫЙ ; дата : ДАТА ]      

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

 [ "Бриджит" , 3.5 , Прошлой ночью ]  

Доступ к компонентам такого кортежа можно получить так, как если бы теги кортежа были атрибутами класса, например, если tему был присвоен вышеуказанный кортеж, то он t.weightимеет значение 3,5.

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

 т . вес := т . вес + 0,5    

Теги кортежа не являются обязательными, поэтому тип кортежа также можно записать как TUPLE [STRING, REAL, DATE]. (В некоторых компиляторах это единственная форма кортежа, поскольку теги были введены в стандарте ECMA.)

Точная спецификация eg TUPLE [A, B, C]заключается в том, что он описывает последовательности как минимум из трех элементов, причем первые три относятся к типам A, B, Cсоответственно. В результате TUPLE [A, B, C]соответствует (может быть присвоено) TUPLE [A, B], to TUPLE [A]и to TUPLE(без параметров), самому верхнему типу кортежа, которому соответствуют все типы кортежей.

Агенты

Механизм «агента» Эйфеля объединяет операции в объекты. Этот механизм можно использовать для итерации, событийно-ориентированного программирования и других контекстов, в которых полезно передавать операции по структуре программы. Другие языки программирования, особенно те, которые подчеркивают функциональное программирование , допускают аналогичный шаблон с использованием продолжений , замыканий или генераторов ; Агенты Eiffel подчеркивают объектно-ориентированную парадигму языка и используют синтаксис и семантику, аналогичные блокам кода в Smalltalk и Ruby .

Например, чтобы выполнить my_actionблок для каждого элемента my_list, можно было бы написать:

 мой список . do_all ( агент my_action )  

Чтобы выполнять my_actionтолько элементы, удовлетворяющие my_condition, можно добавить ограничение/фильтр:

 мой список . do_if ( агент мое_действие , агент мое_условие )    

В этих примерах my_actionи my_conditionесть подпрограммы. Добавление к ним префикса agentдает объект, который представляет соответствующую процедуру со всеми ее свойствами, в частности, возможностью вызова с соответствующими аргументами. Итак, если aпредставляет этот объект (например, потому что aэто аргумент do_all), инструкция

 а . позвони ( [ х ] ) 

вызовет исходную подпрограмму с аргументом x, как если бы мы напрямую вызвали исходную подпрограмму: my_action (x). Здесь аргументы callпередаются в виде кортежа [x].

Можно оставить некоторые аргументы агента открытыми и закрыть другие . Открытые аргументы передаются в качестве аргументов call: они предоставляются во время использования агента . Закрытые аргументы предоставляются во время определения агента . Например, если action2имеется два аргумента, итерация

 мой список . do_all ( действие агента2 ( ? , y ))    

выполняет итерацию action2 (x, y)для последовательных значений x, где второй аргумент остается установленным в y. Знак вопроса ?указывает на открытый аргумент; y— закрытый аргумент агента. Обратите внимание, что базовый синтаксис agent f— это сокращение для agent f (?, ?, ...)всех открытых аргументов. Также можно сделать цель агента открытой через обозначение {T}?где T— тип цели.

Различие между открытыми и закрытыми операндами (операнды = аргументы + цель) соответствует различию между связанными и свободными переменными в лямбда-исчислении . Выражение агента, например, action2 (?, y)с некоторыми закрытыми операндами и некоторыми открытыми, соответствует версии исходной операции, каррированной для закрытых операндов.

Механизм агента также позволяет определять агента без ссылки на существующую подпрограмму (например my_action, my_condition, , action2), через встроенные агенты, как в

мой список . do_all ( агент ( s : STRING ) требует not_void : s / = Void do s.append_character ( ' , ' ) обеспечивает добавление : s.count = old s.count + 1 end ) _ _ _                    

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

 мой список . for_all ( агент ( x : INTEGER ): BOOLEAN do Result := ( x > 0 ) end )           

Текущий механизм агента оставляет возможность ошибки типа во время выполнения (если подпрограмма с n аргументами передается агенту, ожидающему m аргументов с m < n ). Этого можно избежать с помощью проверки во время выполнения с помощью предварительного valid_argumentsусловия call. Доступно несколько предложений по чисто статическому исправлению этой проблемы, включая предложение по изменению языка Ribet et al. [16]

Однажды рутины

Результат процедуры можно кэшировать, используя onceключевое слово вместо do. Непервые вызовы подпрограммы не требуют дополнительных вычислений или выделения ресурсов, а просто возвращают ранее вычисленный результат. Распространенным шаблоном для «однократных функций» является предоставление общих объектов; первый вызов создаст объект, последующие вернут ссылку на этот объект. Типичная схема:

общий_объект : SOME_TYPE после создания результата . make ( args ) — создает объект и возвращает ссылку на него через `Result'. конец       

Возвращаемый объект ( Resultв примере) сам может быть изменяемым, но его ссылка остается прежней.

Часто «однократные процедуры» выполняют необходимую инициализацию: несколько вызовов библиотеки могут включать вызов процедуры инициализации, но только первый такой вызов выполнит необходимые действия. Используя этот шаблон, инициализацию можно децентрализовать, избегая необходимости в специальном модуле инициализации. «Однажды процедуры» по назначению и эффекту аналогичны шаблону Singleton во многих языках программирования, а также шаблону Борга, используемому в Python.

По умолчанию «одна процедура» вызывается один раз для каждого потока . Семантику можно настроить так, чтобы она была один раз для каждого процесса или один раз для каждого объекта , указав ее с помощью «однократного ключа», например once ("PROCESS").

Конверсии

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

(Принцип преобразования) Тип не может одновременно соответствовать и конвертироваться в другой.

Например, NEWSPAPERможет соответствовать PUBLICATION, но INTEGERпреобразуется в REAL(и не наследуется от него).

Механизм преобразования просто обобщает специальные правила преобразования (например, между INTEGERи REAL), которые существуют в большинстве языков программирования, делая их применимыми к любому типу, если соблюдается вышеуказанный принцип. Например, DATEможет быть объявлен класс для преобразования в STRING; это позволяет создать строку из даты просто с помощью

 моя_строка := моя_дата  

как ярлык для использования явного создания объекта с помощью процедуры преобразования:

 создайте мою_строку . make_from_date ( моя_дата )  

Чтобы первая форма стала возможной как синоним второй, достаточно указать процедуру создания (конструктор) make_from_dateв convertпредложении в начале класса.

Другой пример: если в списке есть такая процедура преобразования TUPLE [day: INTEGER; month: STRING; year: INTEGER], то можно напрямую присвоить кортеж дате, вызвав соответствующее преобразование, как в

 День взятия Бастилии := [ 14 , «Июль» , 1789 г. ]    

Обработка исключений

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

Обработчик исключений Eiffel определяется с помощью ключевого слова Rescue . В разделе восстановления ключевое слово retry снова выполняет процедуру. Например, следующая процедура отслеживает количество попыток выполнения процедуры и повторяет ее только определенное количество раз:

Connect_to_server ( server : SOCKET ) — Подключитесь к серверу или откажитесь после 10 попыток. требуется сервер /= Void , а затем сервер . адрес /= Аннулировать локальные попытки : INTEGER do server . Подключитесь, убедитесь, что подключено : сервер . is_connected спасение, если попыток < 10 , то попыток : = попыток + 1 повторение, конец, конец                                  

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

Параллелизм

Доступен ряд сетевых библиотек и библиотек потоков, таких как EiffelNet и EiffelThreads. Модель параллелизма для Eiffel, основанная на концепции проектирования по контракту, — это SCOOP , или Simple Concurrent Object-Oriented Programming , еще не включенная в определение официального языка, но доступная в EiffelStudio . CAMEO [17] — это (нереализованная) вариация SCOOP для Eiffel. Параллелизм также взаимодействует с исключениями. Асинхронные исключения могут быть неприятными (когда подпрограмма вызывает исключение после того, как ее вызывающая сторона завершила работу). [18]

Синтаксис операторов и скобок, команды присваивания

Взгляд Эйфеля на вычисления полностью объектно-ориентирован в том смысле, что каждая операция выполняется относительно объекта, «цели». Например, такое дополнение, как

а + б  

концептуально понимается так, как если бы это был вызов метода

а . плюс ( б ) 

с целью a, функцией plusи аргументом b.

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

плюс псевдоним "+" ( other : INTEGER ): INTEGER -- ... Обычное объявление функции... конец       

Диапазон операторов, которые можно использовать в качестве «псевдонимов», довольно широк; они включают в себя предопределенные операторы, такие как «+», а также «свободные операторы», состоящие из небуквенно-цифровых символов. Это позволяет создавать специальные инфиксные и префиксные обозначения, например, в математических и физических приложениях.

Кроме того, каждый класс может иметь одну функцию с псевдонимом «[]», оператора «скобки», что позволяет использовать обозначение a [i, ...]как синоним того, a.f (i, ...)где fнаходится выбранная функция. Это особенно полезно для контейнерных структур, таких как массивы, хеш-таблицы , списки и т. д. Например, можно записать доступ к элементу хеш-таблицы с помощью строковых ключей.

 номер := телефонная_книга [ "ДЖИЛЛ СМИТ" ]   

«Команды присваивания» — это сопутствующий механизм, разработанный в том же духе, позволяющий по-новому интерпретировать устоявшиеся и удобные обозначения в рамках объектно-ориентированного программирования. Команды присваивателя позволяют использовать синтаксис, подобный присваиванию, для вызова процедур «установщика». Собственно присвоение никогда не может иметь форму, a.x := vпоскольку это нарушает сокрытие информации; вам нужно перейти к команде установки (процедуре). Например, класс хеш-таблицы может иметь функцию и процедуру

псевдоним элемента "[]" ( key : STRING ): ELEMENT [ 3 ] — элемент ключа `key'. -- (запрос «Получатель») do ... end           put ( e : ELEMENT ; key : STRING ) — Вставьте элемент `e', связав его с ключом `key'. -- (команда "Setter") do ... end         

Затем, чтобы вставить элемент, вам нужно использовать явный вызов команды установки:

 [ 4 ] телефонная_книга . put ( New_person , "ДЖИЛЛ СМИТ" )   

Это можно записать эквивалентно как

 [ 5 ] телефонная_книга [ "ДЖИЛЛ СМИТ" ] := Новый_человек    

(точно так же, как это phone_book ["JILL SMITH"]является синонимом number := phone_book.item ("JILL SMITH")), при условии, что объявление itemnow начинается (замена [3]) с

 псевдоним элемента "[]" ( ключ : STRING ): ЭЛЕМЕНТ назначить поставить       

Это объявляет putкоманду присваивателя, связанную с itemпсевдонимом скобки, и в сочетании с псевдонимом скобки делает [5] допустимым и эквивалентным [4]. (Его можно было бы также записать, не используя скобки, как phone_book.item ("JILL SMITH") := New_person.

Примечание. Список аргументов присваивателя a ограничен следующим образом: (тип возвращаемого значения a; весь список аргументов a...)

Лексические и синтаксические свойства

Эйфель не чувствителен к регистру. Токены makeи maKeвсе MAKEобозначают один и тот же идентификатор. См., однако, «правила стиля» ниже.

Комментарии начинаются через --(два последовательных тире) и продолжаются до конца строки.

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

Нет вложенности объявлений функций и классов. В результате структура класса Eiffel проста: несколько предложений уровня класса (наследование, инвариант) и последовательность объявлений функций, все на одном уровне.

Для большей читабельности функции принято группировать в отдельные «пункты функций», при этом стандартный набор тегов основных функций отображается в стандартном порядке, например:

класс HASH_TABLE [ ELEMENT , KEY -> HASHABLE ] наследует TABLE [ ELEMENT ]         особенность -- Инициализация -- ... Объявления команд инициализации (процедур создания/конструкторов) ...   функция -- Доступ -- ... Объявления нелогических запросов о состоянии объекта, например элемент ...   Feature -- Отчет о состоянии -- ... Объявления логических запросов о состоянии объекта, например is_empty ...   Feature -- Изменение элемента -- ... Объявления команд, изменяющих структуру, например put ...   -- и т. д. конец

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

Соглашения о стиле

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

Хотя язык нечувствителен к регистру, стандарты стиля предписывают использовать заглавные буквы для имен классов ( LIST), все строчные буквы для имен функций ( make) и начальные заглавные буквы для констант ( Avogadro). Рекомендуемый стиль также предполагает подчеркивание для разделения компонентов идентификатора, состоящего из нескольких слов, как в average_temperature.

Спецификация Eiffel включает рекомендации по отображению текстов программного обеспечения в наборных форматах: ключевые слова выделены жирным шрифтом, определяемые пользователем идентификаторы и константы показаны italics, комментарии, операторы и знаки препинания — Roman, а текст программы — blueкак в настоящей статье, чтобы отличить его от пояснительный текст. Например, «Привет, мир!» приведенная выше программа будет отображаться в документации Eiffel, как показано ниже:

class HELLO_WORLD create make Feature make do print ( «Привет, мир!» ) end end       

Интерфейсы к другим инструментам и языкам

Eiffel — чисто объектно-ориентированный язык, но он предоставляет открытую архитектуру для взаимодействия с «внешним» программным обеспечением на любом другом языке программирования.

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

Хотя прямой связи между Eiffel и C нет, многие компиляторы Eiffel ( Visual Eiffel является одним исключением) выводят исходный код C в качестве промежуточного языка для передачи компилятору C для оптимизации и переносимости . По сути, они являются примерами транскомпиляторов . tecomp компилятора Eiffel может выполнять код Eiffel напрямую (как интерпретатор), минуя промежуточный код C, или генерировать код C, который будет передан компилятору C для получения оптимизированного собственного кода. В .NET компилятор EiffelStudio напрямую генерирует код CIL (Common Intermediate Language). Компилятор SmartEiffel также может выводить байт-код Java .

Рекомендации

  1. ^ «Эйфелева в двух словах». archive.eiffel.com . Проверено 24 августа 2017 г.
  2. ^ «EiffelStudio 23.09 доступна!». Эйфель.орг . 25 октября 2023 г.
  3. ^ Купер, Питер (2009). Начало Ruby: от новичка до профессионала . От новичка к профессионалу (2-е изд.). Беркли: APress. п. 101. ИСБН 978-1-4302-2363-4. В меньшей степени на Ruby также повлияли Python, LISP, Eiffel, Ada и C++.
  4. ^ «Эйфель – язык». berendeboer.net . Проверено 6 июля 2016 г.
  5. ^ Мейер, Бертран (28 августа 2009 г.). Прикосновение к классу: учимся хорошо программировать с объектами и контрактами. Springer Science & Business Media. ISBN 978-3-540-92144-8.
  6. ^ «Языки программирования — Эйфель» (PDF) . Департамент компьютерных наук, Технологический институт Вирджинии . Проверено 25 марта 2023 г.
  7. ^ Карл Фрисс. «Руководство по синтаксису Эйфеля». Руководство по синтаксису Эйфеля . Проверено 25 марта 2023 г.
  8. ^ Клаус Брабранд. «Язык программирования EIFFEL» (PDF) . ИТ-университет Копенгагена . Проверено 25 марта 2023 г.
  9. ^ Объектно-ориентированное создание программного обеспечения , второе издание, Бертран Мейер , Прентис Холл, 1997, ISBN 0-13-629155-4 
  10. ^ ECMA International: Стандарт ECMA-367 - Eiffel: Язык анализа, проектирования и программирования, 2-е издание (июнь 2006 г.); доступно онлайн по адресу www.ecma-international.org/publications/standards/Ecma-367.htm.
  11. ^ Международная организация по стандартизации: Стандарт ISO/IEC DIS 25436, доступен онлайн по адресу [1]
  12. ^ Бертран Мейер: Перегрузка против объектной технологии, в Журнале объектно-ориентированного программирования (JOOP), том. 14, нет. 4, октябрь – ноябрь 2001 г., доступно онлайн.
  13. ^ «9 НАСЛЕДОВАНИЕ». Архив.eiffel.com. 23 марта 1997 г. Проверено 8 июля 2013 г.
  14. ^ «Множественное наследование и интерфейсы». Артима.com. 16 декабря 2002 г. Проверено 8 июля 2013 г.
  15. ^ «Множественное наследование не является злом». C2.com. 28 апреля 2007 г. Проверено 8 июля 2013 г.
  16. ^ Филипп Рибе, Сирил Адриан, Оливье Зендра, Доминик Колне: Соответствие агентов языку Эйфеля , в Journal of Object Technology , vol. 3, нет. 4 апреля 2004 г., специальный выпуск: Tools USA 2003, стр. 125–143. Доступно онлайн на странице статьи JOT.
  17. ^ Брук, Филипп; Ричард Пейдж (2008). «Камея: альтернативная модель параллелизма для Эйфеля» (PDF) . Формальные аспекты вычислений . Спрингер. 21 (4): 363–391. дои : 10.1007/s00165-008-0096-1. S2CID  18336088.
  18. ^ Брук, Филипп; Ричард Пейдж (2007). «Исключения в параллельной Эйфелевой системе». Журнал объектных технологий . 6 (10): 111–126. дои : 10.5381/jot.2007.6.10.a4 .

Внешние ссылки