Эйфель (язык программирования)
Парадигма | Объектно-ориентированный , на основе классов , общий , параллельный |
---|---|
Разработано | Бертран Мейер |
Разработчик | Эйфелева программа |
Впервые появился | 1986 [1] |
Стабильная версия | ЭйфельСтудия 24.05 [2]
/ 14 июня 2024 г |
Дисциплина набора текста | статический |
Язык реализации | Эйфелева |
Платформа | Кросс-платформенный |
ТЫ | FreeBSD , Linux , macOS , OpenBSD , Solaris , Windows |
Лицензия | двойной и корпоративный |
Расширения имен файлов | .e |
Веб-сайт | Эйфелева |
Основные реализации | |
EiffelStudio , LibertyEiffel , SmartEiffel , Visual Eiffel , Gobo Eiffel, tecomp «Эйфелева компилятор» | |
Под влиянием | |
Ада , Симула , Z | |
Под влиянием | |
Ада 2012 , Альбатрос , C# , D , Java , Racket , Ruby , [3] Сатер , Скала |
Eiffel — это объектно-ориентированный язык программирования, разработанный Бертраном Мейером (сторонником объектно-ориентированной ориентации и автором книги «Объектно-ориентированное создание программного обеспечения ») и Eiffel Software. Мейер придумал этот язык в 1985 году с целью повышения надежности разработки коммерческого программного обеспечения; [4] первая версия стала доступной в 1986 году. В 2005 году Eiffel стал языком, стандартизированным ISO .
Конструкция языка тесно связана с методом программирования Эйфеля. Оба основаны на наборе принципов, включая проектирование по контракту , разделение команд и запросов , принцип единообразного доступа , принцип единственного выбора , принцип открытия-закрытия и разделение опций и операндов .
Многие концепции, первоначально представленные Эйфелем, позже нашли свое применение в Java , C# и других языках. [5] Новые идеи дизайна языка, в частности, благодаря процессу стандартизации Ecma / ISO , продолжают включаться в язык Eiffel.
Характеристики
[ редактировать ]Ключевые характеристики языка Эйфеля включают в себя:
- Объектно-ориентированная структура программы, в которой класс служит базовой единицей декомпозиции. [6]
- Проектирование по контракту тесно интегрировано с другими языковыми конструкциями.
- Автоматическое управление памятью, обычно реализуемое сборкой мусора . [7]
- Наследование , включая множественное наследование , переименование , переопределение , «выбор», несоответствующее наследование и другие механизмы, предназначенные для обеспечения безопасности наследования.
- Ограниченное и неограниченное общее программирование. [8]
- Единая система типов, обрабатывающая семантику значений и ссылок, в которой все типы, включая базовые типы, такие как INTEGER, основаны на классах.
- Статическая типизация
- Void Safety или статическая защита от вызовов по нулевым ссылкам с помощью механизма присоединенных типов.
- Агенты или объекты, которые обертывают вычисления, тесно связанные с замыканиями и лямбда-исчислением .
- Однажды подпрограммы или подпрограммы, выполняемые только один раз, для совместного использования объектов и децентрализованной инициализации.
- Синтаксис на основе ключевых слов в традициях ALGOL / Pascal , но без разделителей, поскольку точки с запятой не являются обязательными, с синтаксисом операторов, доступным для подпрограмм.
- Нечувствительность к регистру
- Простое параллельное объектно-ориентированное программирование ( SCOOP ) облегчает создание нескольких одновременно активных механизмов выполнения на уровне абстракции, превышающем конкретные детали этих механизмов (например, несколько потоков без специального управления мьютексом).
Цели дизайна
[ редактировать ]Эйфель отдает предпочтение декларативным заявлениям над процедурным кодексом и пытается устранить необходимость в инструкциях по бухгалтерскому учету.
Эйфель избегает приемов кодирования или методов кодирования, предназначенных для по оптимизации подсказки компилятору . Цель состоит не только в том, чтобы сделать код более читабельным, но и в том, чтобы позволить программистам сконцентрироваться на важных аспектах программы, не увязая в деталях реализации. Простота Эйфеля призвана способствовать простым, расширяемым, многоразовым и надежным решениям вычислительных задач. Компиляторы компьютерных программ, написанных на Eiffel, предоставляют обширные методы оптимизации, такие как автоматическое встраивание, которые освобождают программиста от части бремени оптимизации.
Фон
[ редактировать ]Eiffel изначально был разработан Eiffel Software, компанией, основанной Бертраном Мейером . «Объектно-ориентированное построение программного обеспечения» содержит подробное рассмотрение концепций и теории объектной технологии, которые привели к созданию Эйфеля. [9]
Целью разработки языка Eiffel, библиотек и методов программирования является предоставление программистам возможности создавать надежные программные модули многократного использования. Eiffel поддерживает множественное наследование , универсальность , полиморфизм , инкапсуляцию , типобезопасные преобразования и ковариацию параметров . Самый важный вклад Эйфеля в разработку программного обеспечения — это проектирование по контракту (DbC), в котором утверждения , предусловия , постусловия и инварианты классов используются, чтобы помочь гарантировать корректность программы без ущерба для эффективности.
Дизайн Эйфеля основан на теории объектно-ориентированного программирования с незначительным влиянием других парадигм или заботой о поддержке устаревшего кода. Eiffel формально поддерживает абстрактные типы данных . По замыслу Эйфеля, текст программного обеспечения должен иметь возможность воспроизводить проектную документацию из самого текста, используя формализованную реализацию «абстрактного типа данных».
Реализации и среды
[ редактировать ]EiffelStudio — это интегрированная среда разработки, доступная по лицензии с открытым исходным кодом или по коммерческой лицензии. Он предлагает объектно-ориентированную среду для разработки программного обеспечения . EiffelEnvision — это плагин для Microsoft Visual Studio , который позволяет пользователям редактировать, компилировать и отлаживать проекты Eiffel из интегрированной среды разработки Microsoft Visual Studio. еще пять реализаций с открытым исходным кодом Доступны : «The Eiffel Compiler» 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 и «The Eiffel Compiler» от Eiffel Software реализуют некоторые из основных новых механизмов, в частности, встроенные агенты, команды присваивания, обозначение скобок, несоответствующее наследование и присоединенные типы. Команда SmartEiffel отошла от этого стандарта, чтобы создать свою собственную версию языка, которая, по их мнению, ближе к оригинальному стилю Eiffel. Object Tools не сообщила, будут ли будущие версии компилятора Eiffel соответствовать этому стандарту. LibertyEiffel реализует диалект где-то между языком SmartEiffel и стандартом.
В стандарте приводятся следующие спецификации предшествующего языка Эйфеля:
- Бертран Мейер: Эйфель: Язык , Прентис Холл, второе издание, 1992 г. (первое издание: 1991 г.)
- Бертран Мейер: Standard Eiffel (пересмотр предыдущей записи), продолжается, с 1997 г. по настоящее время, на странице ETL3 Бертрана Мейера и
- Бертран Мейер: Объектно-ориентированное создание программного обеспечения , Prentice Hall: первое издание, 1988; второе издание, 1997 г.
- Бертран Мейер: Прикосновение к классу: учимся хорошо программировать с помощью объектов и контрактов , Springer-Verlag, 2009 г. ISBN 978-3-540-92144-8 lxiv + 876 страниц. Полноцветная печать, множество цветных фотографий.
Текущая версия стандарта от июня 2006 г. содержит некоторые несоответствия (например, ковариантные переопределения). [ нужна ссылка ] . Комитет ECMA еще не объявил никаких сроков и указаний по устранению несоответствий.
Синтаксис и семантика
[ редактировать ]Общая структура
[ редактировать ]Эйфелева «система» или «программа» представляет собой набор классов . Выше уровня классов Эйфель определяет кластер , который по сути представляет собой группу классов и, возможно, подкластеров (вложенных кластеров). Кластеры — это не синтаксическая языковая конструкция , а скорее стандартное организационное соглашение. Обычно программа Eiffel организуется так, что каждый класс хранится в отдельном файле, а каждый кластер — в каталоге, содержащем файлы классов. В этой организации субкластеры представляют собой подкаталоги. Например, в соответствии со стандартными организационными соглашениями и соглашениями об оформлении, x.e
может быть именем файла, определяющего класс X.
Класс содержит функции , похожие на «подпрограммы», «члены», «атрибуты» или «методы» в других объектно-ориентированных языках программирования. Класс также определяет свои инварианты и содержит другие свойства, такие как раздел «примечания» для документации и метаданных. Стандартные типы данных Эйфеля, такие как INTEGER
, STRING
и ARRAY
, все сами являются классами.
В каждой системе должен быть класс, обозначенный как «корневой», и одна из процедур его создания, обозначенная как «корневая процедура». Выполнение системы состоит из создания экземпляра корневого класса и выполнения его корневой процедуры. Обычно при этом создаются новые объекты, вызываются новые функции и т. д.
У Эйфеля есть пять основных исполняемых инструкций: присваивание, создание объекта, вызов подпрограммы, условие и итерация. Структуры управления Эйфеля строги в обеспечении структурного программирования : каждый блок имеет ровно один вход и ровно один выход.
Обзор
[ редактировать ]В отличие от многих объектно-ориентированных языков, как и Smalltalk , Eiffel не допускает каких-либо присвоений атрибутам объектов, за исключением свойств объекта, что является практическим применением принципа сокрытия информации или абстракции данных, требующего формальных интерфейсов для данных. мутация. Говоря языком других объектно-ориентированных языков программирования, все атрибуты Eiffel «защищены», и для клиентских объектов необходимы «установщики» для изменения значений. Результатом этого является то, что «сеттеры» могут и обычно реализуют инварианты, для которых Eiffel предоставляет синтаксис.
Хотя Eiffel не разрешает прямой доступ к функциям класса клиенту класса, он позволяет определить «команду присваивателя», например:
some_attribute: SOME_TYPE assign set_some_attribute
set_some_attribute (v: VALUE_TYPE)
-- Set value of some_attribute to `v'.
do
some_attribute := v
end
Несмотря на то, что это небольшой поклон всему сообществу разработчиков в разрешении чего-то похожего на прямой доступ (например, тем самым нарушая принцип сокрытия информации), такая практика опасна, поскольку она скрывает или запутывает реальность использования «установщика». На практике лучше перенаправить вызов установщику, чем подразумевать прямой доступ к такой функции, как some_attribute
как в примере кода выше. [ нужна ссылка ]
В отличие от других языков, имеющих понятия «публичный», «защищенный», «частный» и т. д., Eiffel использует технологию экспорта для более точного управления областью действия между классами клиента и поставщика. Видимость функции проверяется статически во время компиляции. Например, (ниже) «{NONE}» аналогично слову «protected» на других языках. Область применения, примененная таким образом к «набору функций» (например, все, что находится ниже ключевого слова «функция» до следующего ключевого слова набора функций или конца класса), может быть изменена в классах-потомках с помощью ключевого слова «экспорт».
feature {NONE} -- Initialization
default_create
-- Initialize a new `zero' decimal instance.
do
make_zero
end
Альтернативно, отсутствие декларации экспорта {x} подразумевает {ANY} и аналогично «публичной» области действия других языков.
feature -- Constants
Наконец, область видимости можно выборочно и точно контролировать для любого класса во вселенной проекта Eiffel, например:
feature {DECIMAL, DCM_MA_DECIMAL_PARSER, DCM_MA_DECIMAL_HANDLER} -- Access
Здесь компилятор разрешит доступ к функциям внутри группы функций только классам, перечисленным в фигурных скобках (например, DECIMAL, DCM_MA_DECIMAL_PARSER, DCM_MA_DECIMAL_HANDLER ).
"Привет, мир!"
[ редактировать ]Внешний вид языка программирования часто передается с помощью фразы «Hello, world!» программа. Такая программа, написанная на Eiffel, может быть:
class
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: detachable SOME_TYPE
use_some_attribute
-- Set value of some_attribute to `v'.
do
if attached some_attribute as l_attribute then
do_something (l_attribute)
end
end
do_something (a_value: SOME_TYPE)
-- Do something with `a_value'.
do
... doing something with `a_value' ...
end
В приведенном выше примере кода показано, как компилятор может статически учитывать надежность того, some_attribute
будет прикреплен или отсоединен в момент использования. Примечательно, что attached
Ключевое слово позволяет использовать «локальное вложение» (например, l_attribute
), область действия которого ограничена только блоком кода, заключенным в конструкцию if-statement. Таким образом, внутри этого небольшого блока кода локальная переменная (например, l_attribute
) может быть статически гарантировано непустым (т.е. недействительным).
Возможности: команды и запросы.
[ редактировать ]Основная характеристика класса заключается в том, что он определяет набор функций: поскольку класс представляет собой набор объектов времени выполнения или «экземпляров», функция представляет собой операцию над этими объектами. Существует два типа функций: запросы и команды. Запрос предоставляет информацию об экземпляре. Команда изменяет экземпляр.
Различие между командой и запросом важно для метода Эйфеля. В частности:
- Принцип единообразного доступа : с точки зрения программного клиента, вызывающего функцию класса, не должно иметь никакого значения, является ли запрос атрибутом (значение поля) или функцией (вычисленное значение). Например,
a_vehicle.speed
может быть атрибутом, доступ к которому осуществляется на объектеa_vehicle
или его можно вычислить с помощью функции, которая делит расстояние на время. Обозначения одинаковы в обоих случаях, поэтому реализацию класса можно легко изменить, не затрагивая клиентское программное обеспечение. - Принцип разделения команд и запросов : запросы не должны изменять экземпляр. Это не языковое правило, а методологический принцип. Таким образом, в хорошем стиле Эйфеля нельзя найти функции «получения», которые что-то изменяют и возвращают результат; вместо этого существуют команды (процедуры) для изменения объектов и запросы для получения информации об объекте, полученной в результате предыдущих изменений.
Перегрузка
[ редактировать ]Eiffel не допускает перегрузку аргументов . Каждое имя объекта внутри класса всегда соответствует определенному объекту внутри класса. Одно имя в одном классе означает одно. Такой выбор дизайна способствует читабельности классов, избегая двусмысленности относительно того, какая подпрограмма будет вызываться при вызове. Это также упрощает языковой механизм; в частности, именно это делает возможным механизм множественного наследования Эйфеля. [12]
Имена, конечно, можно повторно использовать в разных классах. Например, функция плюс (вместе с его инфиксным псевдонимом «+» ) определяется в нескольких классах: ЦЕЛОЕ ЧИСЛО , НАСТОЯЩИЙ , СТРОКА и т. д.
родство
[ редактировать ]Общий класс — это класс, который варьируется в зависимости от типа (например, СПИСОК [ТЕЛЕФОН], список телефонных номеров; АККАУНТ [G->АККАУНТ_ТИП], позволяющий АККАУНТ [ЭКОНОМИЯ] и АККАУНТ [ПРОВЕРКА] и т. д.). Классы могут быть универсальными, чтобы выразить их параметризацию по типам. Общие параметры отображаются в квадратных скобках:
class LIST [G] ...
G известен как «формальный общий параметр». (Эйфель резервирует «аргумент» для подпрограмм и использует «параметр» только для обобщенных классов.) При таком объявлении G представляет внутри класса произвольный тип; поэтому функция может возвращать значение типа G, а подпрограмма может принимать аргумент этого типа:
item: G do ... end
put (x: G) do ... end
The LIST [INTEGER]
и LIST [WORD]
являются «общими производными» этого класса. Разрешенные комбинации (с n: INTEGER
, w: WORD
, il: LIST [INTEGER]
, wl: LIST [WORD]
) являются:
n := il.item
wl.put (w)
INTEGER
и WORD
являются «фактическими общими параметрами» в этих общих выводах.
Также возможно иметь «ограниченные» формальные параметры, для которых фактический параметр должен наследовать от данного класса, «ограничения». Например, в
class HASH_TABLE [G, KEY -> HASHABLE]
вывод HASH_TABLE [INTEGER, STRING]
действителен только в том случае, если STRING
наследует от HASHABLE
(как это действительно происходит в типичных библиотеках Eiffel). Внутри класса, имея KEY
ограничено HASHABLE
означает, что для x: KEY
можно подать заявку на x
все особенности HASHABLE
, как в x.hash_code
.
Основы наследования
[ редактировать ]Чтобы наследовать от одного или нескольких других, класс будет включать в себя inherit
пункт в начале:
class C inherit
A
B
-- ... Rest of class declaration ...
Класс может переопределить (переопределить) некоторые или все унаследованные функции. Об этом необходимо явно объявить в начале занятия через redefine
подпункт пункта о наследовании, как в
class C inherit
A
redefine f, g, h end
B
redefine u, v end
Видеть [13] для полного обсуждения наследования Эйфеля.
Отложенные классы и функции
[ редактировать ]Классы могут быть определены с помощью deferred class
а не с class
чтобы указать, что класс не может быть создан напрямую. классы, не создающие экземпляров, называются абстрактными классами В некоторых других объектно-ориентированных языках программирования . На языке Эйфеля можно создать экземпляр только «эффективного» класса (он может быть потомком отложенного класса). Выполнение функции также можно отложить с помощью deferred
ключевое слово вместо do
пункт. Если класс имеет какие-либо отложенные функции, он должен быть объявлен как отложенный; однако класс без отложенных функций, тем не менее, сам может быть отложен.
Отложенные классы играют примерно ту же роль, что и интерфейсы в таких языках, как Java, хотя многие теоретики объектно-ориентированного программирования полагают, что сами интерфейсы во многом являются ответом на отсутствие в Java множественного наследования (которое есть у Эйфеля). [14] [15]
Переименование
[ редактировать ]Класс, который наследуется от одного или нескольких других, получает все свои функции по умолчанию под их первоначальными именами. Однако он может изменить их имена через rename
статьи. Это требуется в случае множественного наследования, если между унаследованными функциями возникают конфликты имен; без переименования полученный класс нарушит указанный выше принцип отсутствия перегрузки и, следовательно, будет недействительным.
Кортежи
[ редактировать ]Типы кортежей можно рассматривать как простую форму класса, предоставляющую только атрибуты и соответствующую процедуру установки. Типичный тип кортежа читается
TUPLE [name: STRING; weight: REAL; date: DATE]
и может использоваться для описания простого понятия записи о рождении, если класс не нужен. Экземпляр такого кортежа представляет собой просто последовательность значений заданных типов, указанных в скобках, например:
["Brigitte", 3.5, Last_night]
Доступ к компонентам такого кортежа можно получить так же, как если бы теги кортежа были атрибутами класса, например, если t
был назначен вышеуказанный кортеж, тогда t.weight
имеет значение 3,5.
Благодаря понятию команды присваивателя (см. ниже), для назначения компонентов такого кортежа также можно использовать точечную запись, как в
t.weight := t.weight + 0.5
Теги кортежа не являются обязательными, поэтому тип кортежа также можно записать как TUPLE [STRING, REAL, DATE]
. (В некоторых компиляторах это единственная форма кортежа, поскольку теги были введены в стандарте ECMA.)
Точная спецификация, например TUPLE [A, B, C]
заключается в том, что он описывает последовательности как минимум из трех элементов, причем первые три относятся к типам A
, B
, C
соответственно. Как результат, TUPLE [A, B, C]
соответствует (может быть присвоено) TUPLE [A, B]
, к TUPLE [A]
и чтобы TUPLE
(без параметров), самый верхний тип кортежа, которому соответствуют все типы кортежей.
Агенты
[ редактировать ]Механизм «агента» Эйфеля объединяет операции в объекты. Этот механизм можно использовать для итерации, событийно-ориентированного программирования и других контекстов, в которых полезно передавать операции по структуре программы. Другие языки программирования, особенно те, которые подчеркивают функциональное программирование , допускают аналогичный шаблон с использованием продолжений , замыканий или генераторов ; Агенты Eiffel подчеркивают объектно-ориентированную парадигму языка и используют синтаксис и семантику, аналогичные блокам кода в Smalltalk и Ruby .
Например, чтобы выполнить my_action
блок для каждого элемента my_list
, можно было бы написать:
my_list.do_all (agent my_action)
Чтобы выполнить my_action
только на элементах, удовлетворяющих my_condition
, можно добавить ограничение/фильтр:
my_list.do_if (agent my_action, agent my_condition)
В этих примерах my_action
и my_condition
являются рутинами. Добавляя к ним префикс agent
возвращает объект, который представляет соответствующую процедуру со всеми ее свойствами, в частности, возможностью вызова с соответствующими аргументами. Итак, если a
представляет этот объект (например, потому что a
это аргумент для do_all
), инструкция
a.call ([x])
вызовет исходную процедуру с аргументом x
, как если бы мы напрямую вызвали исходную процедуру: my_action (x)
. Аргументы call
передаются как кортеж, здесь [x]
.
Можно оставить некоторые аргументы агента открытыми и закрыть другие . Открытые аргументы передаются в качестве аргументов call
: они предоставляются во время использования агента . Закрытые аргументы предоставляются во время определения агента . Например, если action2
имеет два аргумента, итерация
my_list.do_all (agent action2 (?, y))
повторяет action2 (x, y)
для последовательных значений x
, где второй аргумент остается установленным y
. Вопросительный знак ?
указывает на открытый аргумент; y
— закрытый аргумент агента. Обратите внимание, что основной синтаксис agent f
это сокращение от agent f (?, ?, ...)
со всеми открытыми аргументами. Также можно сделать цель агента открытой через обозначение {T}?
где T
— это тип цели.
Различие между открытыми и закрытыми операндами (операнды = аргументы + цель) соответствует различию между связанными и свободными переменными в лямбда-исчислении . Выражение агента, такое как action2 (?, y)
с некоторыми закрытыми операндами и некоторыми открытыми соответствует версии исходной операции, каррированной на закрытых операндах.
Механизм агента также позволяет определять агента без ссылки на существующую процедуру (например, my_action
, my_condition
, action2
), через встроенные агенты, как в
my_list.do_all (agent (s: STRING)
require
not_void: s /= Void
do
s.append_character (',')
ensure
appended: s.count = old s.count + 1
end)
Передаваемый здесь встроенный агент может иметь все атрибуты обычной процедуры, включая предусловие, постусловие, предложение спасения (здесь не используется) и полную подпись. Это позволяет избежать определения подпрограмм, когда все, что нужно, — это вычисления, которые нужно обернуть в агент. Это особенно полезно для контрактов, например, в инвариантном предложении, которое выражает, что все элементы списка положительны:
my_list.for_all (agent (x: INTEGER): BOOLEAN do Result := (x > 0) end)
Текущий механизм агента оставляет возможность ошибки типа во время выполнения (если подпрограмма с n аргументами передается агенту, ожидающему m аргументов с m < n ). Этого можно избежать с помощью проверки во время выполнения с помощью предварительного условия valid_arguments
из call
. Доступно несколько предложений по чисто статическому исправлению этой проблемы, включая предложение по изменению языка Ribet et al. [16]
Однажды рутины
[ редактировать ]Результат процедуры можно кэшировать с помощью once
ключевое слово вместо do
. Непервые вызовы подпрограммы не требуют дополнительных вычислений или выделения ресурсов, а просто возвращают ранее вычисленный результат. Распространенным шаблоном для «однократных функций» является предоставление общих объектов; первый вызов создаст объект, последующие вернут ссылку на этот объект. Типичная схема:
shared_object: SOME_TYPE
once
create Result.make (args)
-- This creates the object and returns a reference to it through `Result'.
end
Возвращенный объект — Result
в примере — сам может быть изменчивым, но его ссылка остается прежней.
Часто «однократные процедуры» выполняют необходимую инициализацию: несколько вызовов библиотеки могут включать вызов процедуры инициализации, но только первый такой вызов выполнит необходимые действия. Используя этот шаблон, инициализацию можно децентрализовать, избегая необходимости в специальном модуле инициализации. «Однажды процедуры» по назначению и эффекту аналогичны шаблону Singleton во многих языках программирования, а также шаблону Борга, используемому в Python.
По умолчанию «одна процедура» вызывается один раз для каждого потока . Семантику можно настроить так, чтобы она была один раз для каждого процесса или один раз для каждого объекта , указав ее с помощью «однократного ключа», например once ("PROCESS")
.
Конверсии
[ редактировать ]Eiffel предоставляет механизм, позволяющий осуществлять преобразования между различными типами. Механизмы сосуществуют с наследованием и дополняют его. Чтобы избежать путаницы между двумя механизмами, в конструкции реализован следующий принцип:
- (Принцип преобразования) Тип не может одновременно соответствовать и конвертироваться в другой.
Например, NEWSPAPER
может соответствовать PUBLICATION
, но INTEGER
превращается в REAL
(и не наследуется от него).
Механизм преобразования просто обобщает специальные правила преобразования (например, между INTEGER
и REAL
), которые существуют в большинстве языков программирования, что делает их применимыми к любому типу, если соблюдается вышеуказанный принцип. Например, DATE
класс может быть объявлен для преобразования в STRING
; это позволяет создать строку из даты просто с помощью
my_string := my_date
как ярлык для использования явного создания объекта с помощью процедуры преобразования:
create my_string.make_from_date (my_date)
Чтобы первая форма стала возможной как синоним второй, достаточно перечислить процедуру создания (конструктор) make_from_date
в convert
предложение в начале урока.
Другой пример: если существует такая процедура преобразования, указанная в TUPLE [day: INTEGER; month: STRING; year: INTEGER]
, то можно напрямую присвоить кортеж дате, вызвав соответствующее преобразование, как в
Bastille_day := [14, "July", 1789]
Обработка исключений
[ редактировать ]Обработка исключений в Eiffel основана на принципах проектирования по контракту. Например, исключение возникает, когда вызывающая программа не может выполнить предварительное условие или когда подпрограмма не может гарантировать обещанное постусловие. В Eiffel обработка исключений не используется для потока управления или для исправления ошибок ввода данных.
Обработчик исключений Eiffel определяется с помощью ключевое слово спасения . В рамках спасательный отдел, г. Ключевое слово retry выполняет процедуру повторно. Например, следующая процедура отслеживает количество попыток выполнения процедуры и повторяет ее только определенное количество раз:
connect_to_server (server: SOCKET)
-- Connect to a server or give up after 10 attempts.
require
server /= Void and then server.address /= Void
local
attempts: INTEGER
do
server.connect
ensure
connected: server.is_connected
rescue
if attempts < 10 then
attempts := attempts + 1
retry
end
end
Однако этот пример, возможно, некорректен для чего угодно, кроме самых простых программ, поскольку следует ожидать сбоя соединения. Для большинства программ обычное имя типа попытка_connecting_to_server была бы лучше, и постусловие не обещало бы соединение, оставляя на усмотрение вызывающей стороны возможность предпринять соответствующие шаги, если соединение не было открыто.
Параллелизм
[ редактировать ]Доступен ряд сетевых библиотек и библиотек потоков, таких как EiffelNet и EiffelThreads. Модель параллелизма для Eiffel, основанная на концепции проектирования по контракту, — это SCOOP , или Simple Concurrent Object-Oriented Programming , еще не включенная в определение официального языка, но доступная в EiffelStudio . КАМЕЯ [17] представляет собой (нереализованный) вариант SCOOP для Eiffel. Параллелизм также взаимодействует с исключениями. Асинхронные исключения могут быть неприятными (когда подпрограмма вызывает исключение после того, как ее вызывающая сторона завершила работу). [18]
Синтаксис операторов и скобок, команды присваивания
[ редактировать ]Взгляд Эйфеля на вычисления полностью объектно-ориентирован в том смысле, что каждая операция выполняется относительно объекта, «цели». Например, такое дополнение, как
a + b
концептуально понимается так, как если бы это был вызов метода
a.plus (b)
с целью a
, особенность plus
и аргумент b
.
Конечно, первый вариант является общепринятым и обычно предпочтительнее. Синтаксис оператора позволяет использовать любую форму путем объявления функции (например, в INTEGER
, но это относится и к другим базовым классам и может использоваться в любых других, для которых подходит такой оператор):
plus alias "+" (other: INTEGER): INTEGER
-- ... Normal function declaration...
end
Диапазон операторов, которые можно использовать в качестве «псевдонимов», довольно широк; они включают в себя предопределенные операторы, такие как «+», а также «свободные операторы», состоящие из небуквенно-цифровых символов. Это позволяет создавать специальные инфиксные и префиксные обозначения, например, в математических и физических приложениях.
Кроме того, каждый класс может иметь одну функцию с псевдонимом «[]», оператора «скобки», что позволяет использовать обозначение a [i, ...]
как синоним слова a.f (i, ...)
где f
выбранная функция. Это особенно полезно для контейнерных структур, таких как массивы, хеш-таблицы , списки и т. д. Например, можно записать доступ к элементу хеш-таблицы с помощью строковых ключей.
number := phone_book ["JILL SMITH"]
«Команды присваивания» — это сопутствующий механизм, разработанный в том же духе, обеспечивающий новую интерпретацию устоявшихся и удобных обозначений в рамках объектно-ориентированного программирования. Команды присваивателя позволяют использовать синтаксис, подобный присваиванию, для вызова процедур «установщика». Собственно присваивание никогда не может иметь вид a.x := v
поскольку это нарушает сокрытие информации; вам нужно перейти к команде установки (процедуре). Например, класс хеш-таблицы может иметь функцию и процедуру
item alias "[]" (key: STRING): ELEMENT [3]
-- The element of key `key'.
-- ("Getter" query)
do
...
end
put (e: ELEMENT; key: STRING)
-- Insert the element `e', associating it with the key `key'.
-- ("Setter" command)
do
...
end
Затем, чтобы вставить элемент, вам нужно использовать явный вызов команды установки:
[4] phone_book.put (New_person, "JILL SMITH")
Это можно записать эквивалентно как
[5] phone_book ["JILL SMITH"] := New_person
(так же, как phone_book ["JILL SMITH"]
является синонимом number := phone_book.item ("JILL SMITH")
), предоставил декларацию item
теперь начинается (замена [3]) с
item alias "[]" (key: STRING): ELEMENT assign put
Это заявляет put
как команда присваивателя, связанная с item
и в сочетании с псевдонимом скобок делает [5] допустимым и эквивалентным [4]. (Можно также записать без использования скобок так: phone_book.item ("JILL SMITH") := New_person
.
Примечание. Список аргументов присваивателя a ограничен следующим образом: (тип возвращаемого значения a; весь список аргументов a...)
Лексические и синтаксические свойства
[ редактировать ]Эйфель не чувствителен к регистру. Токены make
, maKe
и MAKE
все обозначают один и тот же идентификатор. См., однако, «правила стиля» ниже.
Комментарии представлены --
(два последовательных тире) и продлиться до конца строки.
Точка с запятой в качестве разделителя инструкций не является обязательной. В большинстве случаев точка с запятой просто опускается, за исключением случаев разделения нескольких инструкций в строке. Это приводит к меньшему беспорядку на странице программы.
Нет вложенности объявлений функций и классов. В результате структура класса Eiffel проста: несколько предложений уровня класса (наследование, инвариант) и последовательность объявлений функций, все на одном уровне.
Для большей читабельности функции принято группировать в отдельные «пункты функций», при этом стандартный набор тегов основных функций отображается в стандартном порядке, например:
class HASH_TABLE [ELEMENT, KEY -> HASHABLE] inherit TABLE [ELEMENT]
feature -- Initialization
-- ... Declarations of initialization commands (creation procedures/constructors) ...
feature -- Access
-- ... Declarations of non-boolean queries on the object state, e.g. item ...
feature -- Status report
-- ... Declarations of boolean queries on the object state, e.g. is_empty ...
feature -- Element change
-- ... Declarations of commands that change the structure, e.g. put ...
-- etc.
end
В отличие от большинства языков программирования с фигурными скобками , Эйфель проводит четкое различие между выражениями и инструкциями. Это соответствует принципу разделения команд и запросов метода Эйфеля.
Соглашения о стиле
[ редактировать ]Большая часть документации Eiffel использует особые соглашения о стиле, призванные обеспечить единообразный внешний вид. Некоторые из этих соглашений применимы к самому формату кода, а другие — к стандартному типографскому отображению кода Эйфеля в форматах и публикациях, где эти соглашения возможны.
Хотя язык нечувствителен к регистру, стандарты стиля предписывают использование заглавных букв в именах классов ( LIST
), имена функций пишутся строчными буквами ( make
) и начальные капиталы для констант ( Avogadro
). Рекомендуемый стиль также предполагает подчеркивание для разделения компонентов идентификатора, состоящего из нескольких слов, как в average_temperature
.
Спецификация Eiffel включает рекомендации по отображению текстов программного обеспечения в наборных форматах: ключевые слова выделены жирным шрифтом, определяемые пользователем идентификаторы и константы показаны в italics
, комментарии, операторы и знаки препинания в Roman
, с текстом программы в blue
как и в настоящей статье, чтобы отличить ее от пояснительного текста. Например, «Привет, мир!» приведенная выше программа будет отображаться в документации Eiffel, как показано ниже:
class
HELLO_WORLD
create
make
feature
make
do
print ("Hello, world!")
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 .
Ссылки
[ редактировать ]- ^ «Эйфель в двух словах» . archive.eiffel.com . Проверено 24 августа 2017 г.
- ^ «EiffelStudio 24.05 доступна!» . Эйфель.орг . 14 июня 2024 г.
- ^ Купер, Питер (2009). Начало Ruby: от новичка до профессионала . От новичка к профессионалу (2-е изд.). Беркли: APress. п. 101. ИСБН 978-1-4302-2363-4 .
В меньшей степени на Ruby также повлияли Python, LISP, Eiffel, Ada и C++.
- ^ «Эйфель – язык» . berendeboer.net . Проверено 6 июля 2016 г.
- ^ Мейер, Бертран (28 августа 2009 г.). Прикосновение к классу: учимся хорошо программировать с объектами и контрактами . Springer Science & Business Media. ISBN 978-3-540-92144-8 .
- ^ «Языки программирования — Эйфель» (PDF) . Департамент компьютерных наук, Технологический институт Вирджинии . Проверено 25 марта 2023 г.
- ^ Карл Фрисс. «Руководство по синтаксису Эйфеля» . Руководство по синтаксису Эйфеля . Проверено 25 марта 2023 г.
- ^ Клаус Брабранд. «Язык программирования EIFFEL» (PDF) . ИТ-университет Копенгагена . Проверено 25 марта 2023 г.
- ^ Объектно-ориентированное создание программного обеспечения , второе издание, Бертран Мейер , Прентис Холл, 1997, ISBN 0-13-629155-4
- ^ ECMA International: Стандарт ECMA-367 - Eiffel: Язык анализа, проектирования и программирования, 2-е издание (июнь 2006 г.); доступно онлайн по адресу https://ecma-international.org/publications-and-standards/standards/ecma-367/.
- ^ Международная организация по стандартизации: Стандарт ISO/IEC DIS 25436, доступен онлайн по адресу [1]
- ^ Бертран Мейер: Перегрузка против объектной технологии, в Журнале объектно-ориентированного программирования (JOOP), том. 14, нет. 4, октябрь – ноябрь 2001 г., доступно онлайн.
- ^ «9 НАСЛЕДСТВО» . Архив.eiffel.com. 23 марта 1997 г. Проверено 8 июля 2013 г.
- ^ «Множественное наследование и интерфейсы» . Артима.com. 16 декабря 2002 г. Проверено 8 июля 2013 г.
- ^ «Множественное наследование не является злом» . C2.com. 28 апреля 2007 г. Проверено 8 июля 2013 г.
- ^ Филипп Рибе, Сирил Адриан, Оливье Зендра, Доминик Колне: Соответствие агентов языку Эйфеля , в Journal of Object Technology , vol. 3, нет. 4 апреля 2004 г., специальный выпуск: Tools USA 2003, стр. 125–143. Доступно онлайн на странице статьи JOT.
- ^ Брук, Филипп; Ричард Пейдж (2008). «Камея: альтернативная модель параллелизма для Эйфеля» (PDF) . Формальные аспекты вычислений . 21 (4). Спрингер: 363–391. дои : 10.1007/s00165-008-0096-1 . S2CID 18336088 .
- ^ Брук, Филипп; Ричард Пейдж (2007). «Исключения в параллельной Эйфелевой системе» . Журнал объектных технологий . 6 (10): 111–126. дои : 10.5381/jot.2007.6.10.a4 .
Внешние ссылки
[ редактировать ]- Веб-сайт Eiffel Software компании, представившей Eiffel, назывался Interactive Software Engineering (ISE).
- LibertyEiffel веб-сайт бесплатной системы разработки GNU Eiffel.