| パラダイム | オブジェクト指向 |
|---|---|
| 開発者 | RemObjects ソフトウェア |
| 初登場 | 2005年[1] |
| プラットフォーム | 共通言語インフラストラクチャ、Java、Cocoa、CPU ネイティブ、Windows 32/64 ビット、Linux 32/64 ビット、WebAssembly |
| ライセンス | 試用版 |
| Webサイト | elementscompiler.com/elements/oxygene/ |
| 影響を受けた | |
| DelphiのObject Pascal、C# | |
Oxygene(旧称Chrome)は、RemObjects SoftwareがMicrosoft のCommon Language Infrastructure、Javaプラットフォーム、およびCocoa向けに開発したプログラミング言語です。Oxygene はDelphiのObject Pascalに基づいていますが、 C#、Eiffel、Java、F#などの言語 の影響も受けています 。
現在廃止されているDelphi.NETと比較すると、Oxygene は完全な下位互換性を重視していませんが、言語の「再発明」として設計されており、管理された開発プラットフォームの良き一員となり、.NETおよび Java ランタイムによって提供されるすべての機能とテクノロジを活用します。
Oxygene は商用製品であり、 Windows 上のMicrosoftのVisual Studio IDE と、macOSで使用するための Fire と呼ばれる独自の IDE に完全に統合されています。Oxygene は、 C#、Swift、Java、Go、Mercury (Visual Basic (.NET) ベース)に次いで、基盤となる Elements Compiler ツールチェーンでサポートされている 6 つの言語の 1 つです。
2008年から2012年にかけて、RemObjects Softwareは、 EmbarcaderoにコンパイラとIDEテクノロジーのライセンスを供与し、Embarcadero Prism製品のバックエンドコンパイラとして使用しました。[2] 2011年秋から、Oxygeneは2つの別々のエディションで利用可能になり、2番目のエディションではJavaおよびAndroidランタイムのサポートが追加されました。XE4のリリース以降、Embarcadero PrismはRAD Studio SKUの一部ではなくなりました。Prismの顧客がOxygeneに移行するためのサポートとアップグレードパスが多数存在します。[3] 2016年現在、Oxygeneのエディションは1つだけであり、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。
クラス演算子implicit ( i : Integer ) : MyClass ;
演算子のオーバーロードでは、各演算子に名前があり、その名前を演算子のオーバーロード構文で使用する必要があることに注意してください。たとえば、「+」はOxygeneでは有効なメソッド名ではないためです。[4]
プログラム構造
Oxygene は Delphi のように「ユニット」を使用しませんが、.NET名前空間を使用して型を整理およびグループ化します。名前空間は複数のファイル (およびアセンブリ) にまたがることができますが、1 つのファイルには 1 つの名前空間の型しか含めることができません。この名前空間は、ファイルの一番上で定義されます。
名前空間 ConsoleApplication1;
Oxygene ファイルは、Delphi で知られている構造であるインターフェイス セクションと実装セクションに分かれています。インターフェイス セクションは、名前空間の宣言に続きます。このセクションにはuses、Oxygene で他の名前空間から型をインポートする句が含まれています。
System.Linqを使用します。
インポートされた名前空間は、プロジェクト自体または参照されたアセンブリ内にある必要があります。C# とは異なり、Oxygene では、名前空間に対してエイリアス名を定義できず、単一の型名に対してのみ定義できます (以下を参照)。
句の後に、usesファイルには Delphi で知られているような型宣言が含まれます。
インタフェース
type
ConsoleApp =クラスpublicクラスメソッドMain ; end ;
C# と同様に、Main メソッドはすべてのプログラムのエントリ ポイントです。args : Array of Stringプログラムにコマンド ライン引数を渡すためのパラメーターを持つことができます。
キーワードを繰り返さずに、さらに多くの型を宣言できますtype。
宣言されたメソッドの実装は実装セクションに配置されます。
実装
クラスメソッドConsoleApp.Main ; begin //ここに独自のコードを追加しますConsole.WriteLine ( ' Hello World. ' ) ; end ;
終わり。
ファイルは常にend.
種類
.NET 言語として、Oxygene は .NET 型システムを使用します。値型 (構造体など) と参照型 (配列やクラスなど) があります。
Oxygene は独自の「定義済み」型を導入していませんが、それらのいくつかに対してより「パスカル風」な汎用名を提供しています。[5]たとえば、 はSystem.Int32として使用できInteger、Boolean( System.Boolean)、Char( System.Char)、Real( System.Double) もパスカル型名のファミリーに加わります。.NET の一部であるこれらの型の構造体の特性は完全に保持されます。
すべての .NET 言語と同様に、Oxygene の型には可視性があります。Oxygene では、デフォルトの可視性は でassembly、これは C# の可視性に相当しますinternal。その他の可能な型の可視性は ですpublic。
タイプ
MyClass = public class end ;
定義されたすべてのタイプ (クラス、インターフェース、レコードなど) に対して可視性を設定できます。
型に対してエイリアス名を定義することができ、これはローカルまたは他の Oxygene アセンブリで使用できます。
type
IntList = public List < Integer >; //他の Oxygene アセンブリで表示可能SecretEnumerable = IEnumerable < String >; //他のアセンブリでは表示不可
パブリック型エイリアスは他の言語では表示されません。
記録
レコードは、Oxygene では .NET 構造体と呼ばれます。レコードはクラスと同じように宣言されますが、次のrecordキーワードを使用します。
タイプ
MyRecord = recordメソッドFoo ;終了;
レコードは単なる .NET 構造体なので、フィールド、メソッド、プロパティを持つことができますが、継承はなく、インターフェイスを実装することはできません。
インターフェース
インターフェイスは .NET の世界では極めて重要な概念であり、フレームワーク自体がインターフェイスを多用しています。インターフェイスとは、インターフェイスを実装する際にクラスが実装しなければならないメソッド、プロパティ、イベントの小さなセットの仕様です。たとえば、インターフェイスはシーケンスを反復処理するために使用されるメソッドIEnumerable<T>を指定しますGetEnumerator。
インターフェースはクラスと同じように宣言されます。
タイプ
MyInterface =パブリックインターフェイスメソッドMakeItSo : IEnumerable ;プロパティBar : String読み取り書き込み;終了;
プロパティの場合、ゲッターとセッターは明示的に指定されないことに注意してください。
代表者
デリゲートはメソッドのシグネチャを定義するため、これらのメソッドをパラメータ (コールバックなど) で渡したり、変数に格納したりできます。デリゲートは関数ポインターと同等のタイプセーフな NET です。イベントでも使用されます。デリゲートにメソッドを割り当てるときは、演算子を使用する必要があります@。これにより、コンパイラはメソッドを呼び出すのではなく、割り当てるだけであることを認識します。
Oxygene は匿名デリゲートを作成できます。たとえば、Invokeデリゲートを宣言せずにコントロールのメソッドにメソッドを渡すことが可能です。
メソッドMainForm.MainForm_Load ( sender : System.Object ; e : System.EventArgs ) ;
beginInvoke
( @DoSomething ) ; end ;
メソッドのシグネチャを持つ匿名デリゲートがDoSomethingコンパイラによって作成されます。
Oxygene は多態的なデリゲートをサポートしています。つまり、降順型のパラメータを持つデリゲートは割り当て互換性があります。 と という 2 つのクラスがあるとするMyClassとMyClassEx = class(MyClass)、次のコードでは はBlubbExと割り当て互換性がありますBlubb。
型
デリゲートBlubb (送信者: Object ; m : MyClass ) ;デリゲートBlubbEx (送信者: Object ; mx : MyClassEx ) ;
フィールドの型がこのインターフェースを実装している場合、フィールドを使用してインターフェースの実装を委任できます。
Implementor = public class ( IMyInterface ) // ... インターフェースを実装します ...終了;
MyClass = public class ( IMyInterface ) fSomeImplementor : Implementor ; public implements IMyInterface ; // インターフェイスの実装を処理しますend ;
この例では、コンパイラはMyClassのメソッド/プロパティを呼び出すにパブリックメソッドとプロパティを作成しfSomeImplementor、IMyInterfaceのメンバーを実装します。これを使用して、ミックスインのような機能を提供できます。[6]
匿名メソッド
匿名メソッドは他のメソッド内に実装されます。デリゲート フィールド内に格納されていない限り、メソッドの外部からはアクセスできません。匿名メソッドは、実装されているメソッドのローカル変数と、それが属するクラスのフィールドを使用できます。
匿名メソッドは、GUI スレッドで実行されることになっているコードを操作する場合に特に便利です。これは、.NET ではメソッドをメソッドに渡すことによって実行されますInvoke( Control.InvokeWinForms では 、Dispatcher.InvokeWPF では )。
method Window1 . PredictNearFuture ; // インターフェイスで async として宣言
begin
// ... ここで結果を計算し、変数 "theFuture" に格納しますDispatcher . Invoke ( DispatcherPriority . ApplicationIdle , method ; begin theFutureTextBox . Text := theFuture ; end ) ; end ;
匿名メソッドにもパラメータを設定できます。
method Window1 . PredictNearFuture ; // インターフェイスで async として宣言
begin
// ... ここで結果を計算し、変数 "theFuture" に格納しますDispatcher . Invoke ( DispatcherPriority . ApplicationIdle , method ( aFuture : String ) ; begin theFutureTextBox . Text := aFuture ; end , theFuture ) ; end ;
どちらのソースコードも匿名デリゲートを使用します。
物件通知
プロパティ通知は主にデータ バインディングに使用され、GUI はプロパティの値がいつ変更されたかを知る必要があります。.NET フレームワークは、この目的のためにインターフェイスINotifyPropertyChangedとINotifyPropertyChanging(.NET 3.5 では) を提供します。これらのインターフェイスは、プロパティが変更されたとき、または変更されたときに発生するイベントを定義します。
Oxygene はnotify、プロパティで使用できる修飾子を提供します。この修飾子を使用すると、コンパイラはクラスにインターフェイスを追加して実装し、プロパティが変更されたとき、または変更されたときにイベントを発生させるコードを作成します。
property Foo : String read fFoo write SetFoo ;通知; property Bar : String ;通知'Blubb' ; //プロパティ "Bar" ではなく "Blubb" が変更されたことを通知します
この修飾子は、セッター メソッドを持つプロパティで使用できます。イベントを発生させるコードは、コンパイル時にこのメソッドに追加されます。
コード例
こんにちは世界
名前空間HelloWorld ;
インターフェース
タイプ
HelloClass =クラスpublicクラスメソッドMain ;終了;
実装
クラスメソッドHelloClass.Main ; begin writeLn ( 'Hello World ! ' ) ; end ;
終わり。
汎用コンテナ
名前空間GenericContainer ;
インターフェース
type
TestApp =クラスpublicクラスメソッドMain ; end ;
Person =クラスpublicプロパティFirstName : String ;プロパティLastName : String ;終了;
実装
System.Collections.Genericを使用します。
クラスメソッドTestApp.Main ; begin var myList := new List < Person >; //型推論myList.Add ( new Person ( FirstName := ' John ' , LastName := 'Doe' ) ) ; myList.Add ( new Person ( FirstName : = ' Jane' , LastName := 'Doe' )) ; myList.Add ( new Person ( FirstName := 'James' , LastName : = ' Doe ' ) ) ; Console.WriteLine ( myList [ 1 ] .FirstName ) ; //キャストは不要Console.ReadLine ; end ;
終わり。
一般的な方法
名前空間GenericMethodTest ;
インターフェース
type
GenericMethodTest = staticクラスpublicクラスメソッドMain ; privateクラスメソッドSwap < T > ( var left , right : T ) ;クラスメソッドDoSwap < T > ( left , right : T ) ; end ;
実装
クラスメソッドGenericMethodTest.DoSwap < T > ( left , right : T ) ; begin var a : = left ; var b := right ; Console.WriteLine ( 'Type: {0}' , typeof ( T )) ; Console.WriteLine ( '-> a = {0} , b = {1}' , a , b ) ; Swap < T > ( var a , var b ) ; Console.WriteLine ( '- > a = {0} , b = {1}' , a , b ) ; end ;
クラスメソッドGenericMethodTest.Main ; begin var a : = 23 ; // 型推論var b := 15 ; DoSwap < Integer > ( a , b ) ; //このメソッドでは Object へのダウンキャストは行われません。
var aa := 'abc' ; // 型推論var bb := 'def' ; DoSwap < String > ( aa , bb ) ; // このメソッドでは Object へのダウンキャストは行われません。
DoSwap ( 1.1 , 1.2 ) ; //ジェネリックパラメータの型推論Console.ReadLine ( ) ; end ;
クラスメソッドGenericMethodTest.Swap < T > ( var left , right : T ) ; begin var temp : = left ; left : = right ; right := temp ; end ;
終わり。
プログラム出力:
型: System.Int32 -> a = 23、b = 15 -> a = 15、b = 23 タイプ: System.String -> a = abc、b = def -> a = 定義、b = abc タイプ: System.Double -> a = 1,1、b = 1,2 -> a = 1,2、b = 1,1
Delphi と Oxygene の違い
unit: namespaceキーワードに置き換えられました。Oxygene はファイルごとではなくプロジェクトごとにコンパイルするため、ファイル名に依存しません。代わりに、ユニットまたは namespace キーワードを使用して、そのファイルで定義されているすべての型が定義されているデフォルトの名前空間を示します。procedureandfunction:methodが推奨キーワードですがprocedure、functionそれでも機能します。overload: Oxygeneではすべてのメソッドがデフォルトでオーバーロードされるため、特別なキーワードは必要ありません。.Create(): このコンストラクタ呼び出しはキーワードに置き換えられました。レガシーな理由から、new引き続き有効にすることができます。project optionsstring: 文字列内の文字はゼロベースで読み取り専用です。文字列には nil 値が含まれることがあるため、空の文字列に対するテストだけでは十分ではない場合があります。
批判
大きな変更を加えずに Win32 Delphi コードを Oxygene に移植したいと考えている人がいます[誰ですか? ]。これは不可能です。Oxygene は Delphi に似ていますが、単純な再コンパイルでは互換性がなくなるほどの変更が加えられているためです。名前から Delphi の別のバージョンのように見えますが、それは完全に真実ではありません。[7]
言語の違いに加えて、ビジュアルコンポーネントライブラリフレームワークはOxygeneでは利用できません。[8]従来のDelphiコードはVCLに大きく依存しているため、移植はさらに困難になります。
参照
参考文献
- ^ “Oxygene 言語の進化 | Oxygene | Elements”. 2018 年 1 月 5 日時点のオリジナルよりアーカイブ。2018 年 1 月 4 日閲覧。
- ^ 「Embarcadero Prism ページ、ページの下部に RemObjects Oxygene を搭載していることを示す画像」。2011 年 12 月 27 日時点のオリジナルよりアーカイブ。2011年 12 月 14 日閲覧。
- ^ 「Prism XE4、どこにいるの? | RemObjects Blogs」。2013年6月20日時点のオリジナルよりアーカイブ。2013年6月6日閲覧。
- ^ 「演算子オーバーロード - Delphi Prism」。2011 年 7 月 8 日時点のオリジナルよりアーカイブ。2010年 1 月 9 日閲覧。
- ^ 「組み込み型 - Delphi Prism」。2011 年 7 月 8 日時点のオリジナルよりアーカイブ。2010 年 1 月 10 日閲覧。
- ^ 「Mixin のような機能を提供する - Delphi Prism」。2011 年 7 月 8 日にオリジナルからアーカイブ。2010 年 1 月 17 日に取得。
- ^ 「Oxygene は Delphi Win32 ではないと人々が指摘する Stack Overflow のディスカッション」。2012 年 10 月 25 日時点のオリジナルよりアーカイブ。2016年 7 月 25 日閲覧。
- ^ 「Delphi Prism 2010 のレビューでは、3 番目の段落で VCL.net は利用できないと述べられています」。2009 年 9 月 4 日にオリジナルからアーカイブ。2009年 12 月 14 日に取得。
外部リンク
- 公式サイト
