Oxygene (ранее известный как Chrome ) — язык программирования , разработанный RemObjects Software для Microsoft Common Language Infrastructure , платформы Java и Cocoa . Oxygene основан на Delphi Object Pascal , но также имеет влияние C# , Eiffel , Java , F# и других языков.
По сравнению с ныне устаревшим Delphi.NET , Oxygene не делает упор на полную обратную совместимость, но предназначен для «переосмысления» языка, добросовестного использования управляемых платформ разработки и использования всех функций и технологий, предоставляемых Среды выполнения .NET и Java.
Oxygene является коммерческим продуктом и предлагает полную интеграцию с Microsoft Visual Studio IDE для Windows, а также с собственной IDE под названием Fire для использования на macOS . Oxygene — один из шести языков, поддерживаемых базовым набором инструментов Elements Compiler, наряду с C# , Swift , Java , Go и Mercury (на основе Visual Basic.NET ).
С 2008 по 2012 год RemObjects Software передала Embarcadero лицензию на свой компилятор и технологию IDE для использования в их продукте Embarcadero Prism . [2] Начиная с осени 2011 года, Oxygene стал доступен в двух отдельных редакциях, причем во вторую версию была добавлена поддержка сред выполнения Java и Android. Начиная с выпуска XE4, Embarcadero Prism больше не является частью SKU RAD Studio. Для клиентов Prism существует множество способов поддержки и обновления для перехода на Oxygene. [3] По состоянию на 2016 год существует только одна редакция Oxygene, которая позволяет разрабатывать приложения для Windows или macOS и позволяет создавать исполняемые файлы для Windows, Linux, WebAssembly .NET, iOS, Android, Java и macOS.
Язык Oxygene берет свое начало от Object Pascal в целом и Delphi в частности, но был разработан с учетом принципов программирования .NET и создания полностью совместимых с CLR сборок. Поэтому некоторые второстепенные функции языка, известные из Object Pascal/Delphi, были исключены или пересмотрены, в то время как в язык было добавлено множество новых и более современных функций, таких как универсальные функции или последовательности и запросы.
Oxygene — это объектно-ориентированный язык, что означает, что для разработки программ он использует классы, которые могут хранить данные и выполнять код. [ необходимы пояснения ] Классы — это «прототипы» объектов, например, идея яблока — это прототип яблока, которое можно купить в магазине. Известно, что яблоко имеет цвет и что его можно очистить: это данные и исполняемый «код» класса яблок.
Oxygene обеспечивает поддержку некоторых функций параллельного программирования на уровне языка. Цель состоит в том, чтобы использовать все ядра или процессоры компьютера для повышения производительности. Для достижения этой цели задачи необходимо распределить между несколькими потоками. Класс .NET Framework предлагал ThreadPool
способ эффективной работы с несколькими потоками. Библиотека параллельных задач (TPL) была представлена в .NET 4.0, чтобы предоставить больше возможностей для параллельного программирования.
Операторы можно перегрузить в Oxygene, используя class operator
синтаксис:
неявный оператор класса ( i : Integer ) : MyClass ;
Обратите внимание, что для перегрузки операторов каждый оператор имеет имя, которое необходимо использовать в синтаксисе перегрузки операторов, поскольку, например, «+» не будет допустимым именем метода в Oxygene. [4]
Oxygene не использует «единицы измерения», как Delphi, а использует пространства имен .NET для организации и группировки типов. Пространство имен может охватывать несколько файлов (и сборок), но один файл может содержать типы только одного пространства имен. Это пространство имен определено в самом верху файла:
пространство имен ConsoleApplication1;
Файлы Oxygene разделены на раздел интерфейса и раздел реализации, который представляет собой структуру, известную из Delphi. Раздел интерфейса следует за объявлением пространства имен. Он содержит uses
предложение, которое в Oxygene импортирует типы из других пространств имен:
использует систему . Линк ;
Импортированные пространства имен должны находиться в самом проекте или в сборках, на которые имеются ссылки. В отличие от C#, в Oxygene имена псевдонимов не могут быть определены для пространств имен, а только для имен одного типа (см. ниже).
После этого uses
предложения файл содержит объявления типов, известные из Delphi:
интерфейсвведите ConsoleApp = класс метод открытого класса Main ; конец ;
Как и в C#, метод Main является точкой входа для каждой программы. Он может иметь параметр args : Array of String
для передачи аргументов командной строки в программу.
Можно объявить больше типов без повторения type
ключевого слова.
Реализация заявленных методов вынесена в раздел реализации:
выполнениеметод класса ConsoleApp . Основной ; начало // добавьте сюда свой собственный код Console . WriteLine ( 'Привет, мир.' ) ; конец ; конец .
Файлы всегда заканчиваются наend.
В качестве языка .NET Oxygene использует систему типов .NET: существуют типы значений (например, структуры) и ссылочные типы (например, массивы или классы).
Хотя Oxygene не вводит собственные «предопределенные» типы, он предлагает более «паскалистские» общие имена для некоторых из них, [5] так, что, например, их System.Int32
можно использовать как Integer
и Boolean
( System.Boolean
), Char
( System.Char
), Real
( System.Double
) присоединяются к семейству имен типов Паскаля тоже. Структурный характер этих типов, являющийся частью .NET, полностью сохраняется.
Как и во всех языках .NET, типы в Oxygene имеют видимость. В Oxygene видимость по умолчанию равна assembly
, что эквивалентно internal
видимости в C#. Другой возможный тип видимости — public
.
введите MyClass = конец публичного класса ;
Видимость может быть установлена для каждого определенного типа (классы, интерфейсы, записи и т. д.).
Для типов можно определить псевдоним, который можно использовать локально или в других сборках Oxygene.
введите IntList = общедоступный список < Целое число >; //видим в других Oxygene- сборках SecretEnumerable = IEnumerable <String> ; //не видно в других сборках
Псевдонимы общедоступного типа не будут видны для других языков.
Записи — это то, что структуры .NET называются в Oxygene. Они объявляются так же, как классы, но с record
ключевым словом:
введите MyRecord = метод записи Foo ; конец ;
Поскольку это всего лишь структуры .NET, записи могут иметь поля, методы и свойства, но не имеют наследования и не могут реализовывать интерфейсы .
Интерфейсы — очень важная концепция в мире .NET, сама платформа активно их использует. Интерфейсы — это спецификация небольшого набора методов, свойств и событий, которые класс должен реализовать при реализации интерфейса. Например, интерфейс IEnumerable<T>
определяет GetEnumerator
метод, который используется для перебора последовательностей.
Интерфейсы объявляются так же, как классы:
тип MyInterface = метод открытого интерфейса MakeItSo : IEnumerable ; свойство Bar : чтение строки ; запись ; конец ;
Обратите внимание, что для свойств методы получения и установки явно не указаны.
Делегаты определяют сигнатуры методов, так что эти методы можно передавать в параметрах (например, обратные вызовы) или сохранять в переменных и т. д. Они являются типобезопасным NET-эквивалентом указателей на функции. Они также используются на мероприятиях. При назначении метода делегату необходимо использовать оператор @
, чтобы компилятор знал, что метод нужно не вызывать, а просто назначить его.
Oxygene может создавать анонимных делегатов; например, методы можно передать методу Invoke
элемента управления без объявления делегата:
метод MainForm . MainForm_Load ( отправитель : System . Object ; e : System . EventArgs ) ; начать вызов ( @DoSomething ) ; _ конец ;
Анонимный делегат с сигнатурой метода DoSomething
будет создан компилятором.
Oxygene поддерживает полиморфные делегаты, что означает, что делегаты, имеющие параметры нисходящих типов, совместимы по назначению. Предположим, что два класса MyClass
и MyClassEx = class(MyClass)
, тогда в следующем коде BlubbEx
совместимо по присваиванию с Blubb
.
введите делегат Блабб ( отправитель : Object ; m : MyClass ) ; делегат BlubbEx ( отправитель : Object ; mx : MyClassEx ) ;
Поля можно использовать для делегирования реализации интерфейса, если тип, к которому они относятся, реализует этот интерфейс:
Implementor = public class ( IMyInterface ) // ... реализовать интерфейс ... end ; MyClass = общественный класс ( IMyInterface ) fSomeImplementor : Implementor ; public реализует IMyInterface ; //заботится о реализации интерфейса end ;
В этом примере компилятор создаст общедоступные методы и свойства в MyClass
, которые вызывают методы/свойства fSomeImplementor
для реализации членов IMyInterface. Это можно использовать для обеспечения функциональности, подобной миксину. [6]
Анонимные методы реализуются внутри других методов. Они недоступны вне метода, если не сохранены внутри поля делегата. Анонимные методы могут использовать локальные переменные метода, в котором они реализованы, и поля класса, к которому они принадлежат.
Анонимные методы особенно полезны при работе с кодом, который должен выполняться в потоке графического интерфейса, что в .NET делается путем передачи метода do the Invoke
методу ( Control.Invoke
в WinForms, Dispatcher.Invoke
в WPF):
метод Окно1 . Предсказать ближайшее будущее ; //объявлен как асинхронный в начале интерфейса // ... Результат вычисления здесь, сохранение в переменной "theFuture" Dispatcher . Invoke ( DispatcherPriority . ApplicationIdle , метод ; начало theFutureTextBox . Text : = theFuture ; конец ) ; конец ;
Анонимные методы также могут иметь параметры:
метод Окно1 . Предсказать ближайшее будущее ; //объявлен как асинхронный в начале интерфейса // ... Результат вычисления здесь, сохранение в переменной "theFuture" Dispatcher . Invoke ( DispatcherPriority . ApplicationIdle , метод ( aFuture : String ) ; начало theFutureTextBox . Text := aFuture ; конец , theFuture ) ; конец ;
Оба исходных кода используют анонимные делегаты.
Уведомление о свойстве используется в основном для привязки данных, когда графический интерфейс должен знать, когда изменяется значение свойства. Платформа .NET предоставляет для этой цели интерфейсы INotifyPropertyChanged
и INotifyPropertyChanging
(в .NET 3.5). Эти интерфейсы определяют события, которые должны запускаться при изменении/изменении свойства.
Oxygene предоставляет notify
модификатор, который можно использовать в свойствах. Если используется этот модификатор, компилятор добавит интерфейсы в класс, реализует их и создаст код для вызова событий при изменении/изменении свойства.
свойство Foo : чтение строки fFoo write SetFoo ; поставить в известность ; свойство Bar : String ; уведомить «Блабб» ; //сообщим, что свойство "Blubb" было изменено вместо "Bar"
Модификатор можно использовать для свойств, имеющих метод установки. Код для вызова событий будет добавлен к этому методу во время компиляции.
пространство имен HelloWorld ; интерфейстип HelloClass = класс метод открытого класса Main ; конец ; выполнениеметод класса HelloClass . Основной ; начать writeLn ( 'Привет, мир!' ) ; конец ; конец .
пространство имен GenericContainer ; интерфейстип TestApp = класс метод открытого класса Main ; конец ; Person = публичное свойство класса FirstName : String ; свойство LastName : String ; конец ; выполнениеиспользует систему . Коллекции . Общий ; метод класса TestApp . Основной ; начать вар myList : = новый список < человек >; //вывод типа myList . Добавить ( новый человек ( Имя := 'Джон' , Фамилия := 'Доу' )) ; мой список . Добавить ( новый человек ( Имя := 'Джейн' , Фамилия := 'Доу' )) ; мой список . Добавить ( новый человек ( Имя := 'Джеймс' , Фамилия := 'Доу' )) ; Консоль . WriteLine ( myList [ 1 ] .FirstName ) ; _ // Приведение не требуется Console . ЧитатьСтроку ; конец ; конец .
пространство имен GenericMethodTest ; интерфейстип GenericMethodTest = статический класс метод открытого класса Main ; метод частного класса Swap <T> ( var left , right : T ) ; _ _ метод класса DoSwap <T> ( слева , справа : T ) ; _ _ конец ; выполнениеметод класса GenericMethodTest . DoSwap <T> ( слева , справа : T ) ; _ _ начать вар а := влево ; вар б := правильно ; Консоль . WriteLine ( 'Тип: {0}' , typeof ( T )) ; Консоль . WriteLine ( '-> a = {0}, b = {1}' , a , b ) ; Обмен <T> ( вар а , вар б ) ; _ _ Консоль . WriteLine ( '-> a = {0}, b = {1}' , a , b ) ; конец ; метод класса GenericMethodTest . Основной ; начать вар а := 23 ; // вывод типа var b := 15 ; DoSwap < Целое число > ( a , b ) ; // в этом методе нет понижающего приведения к Object. вар аа := 'abc' ; // вывод типа var bb := 'def' ; DoSwap <String> ( aa , bb ) ; _ _ // в этом методе нет понижающего приведения к Object. DoSwap ( 1.1 , 1.2 ) ; // определение типа для общих параметров Console . ЧитатьСтроку () ; конец ; метод класса GenericMethodTest . Поменять <T> ( вар влево , вправо : T ) ; _ _ начать вар темп := слева ; влево := вправо ; правильно : = температура ; конец ; конец .
Выход программы:
Тип: System.Int32-> а = 23, б = 15-> а = 15, б = 23Тип: System.String-> а = abc, b = def-> а = защита, б = abcТип: Система.Двойной-> а = 1,1, б = 1,2-> а = 1,2, б = 1,1
unit
: заменено ключевым словом пространства имен . Поскольку Oxygene компилирует не для каждого файла, а для каждого проекта, это не зависит от имени файла. Вместо этого ключевое слово unit или namespace используется для обозначения пространства имен по умолчанию, в котором определены все типы для этого файла.procedure
и function
: method
является предпочтительным ключевым словом, хотя procedure
оно function
все еще работает.overload
: В Oxygene все методы по умолчанию перегружены, поэтому для этого не требуется специального ключевого слова..Create()
: этот вызов конструктора заменен ключевым new
словом. Его все еще можно включить по project options
устаревшим причинам.string
: символы в строках начинаются с нуля и доступны только для чтения. Строки могут иметь нулевые значения, поэтому проверки пустой строки не всегда достаточно.Некоторые люди [ кто? ] хотели бы перенести свой код Win32 Delphi на Oxygene без внесения серьезных изменений. Это невозможно, потому что, хотя Oxygene и выглядит как Delphi, в нем достаточно изменений, чтобы сделать его несовместимым для простой перекомпиляции. Хотя название напоминает другую версию Delphi, это не совсем так. [7]
Помимо языковой разницы, в Oxygene недоступна платформа библиотеки визуальных компонентов . [8] Это еще больше усложняет портирование, поскольку классический код Delphi в значительной степени зависит от VCL.