Eiffel(プログラミング言語)

ウィキペディアから、無料の百科事典
ナビゲーションにジャンプ 検索にジャンプ
エッフェル
エッフェルのロゴ
パラダイムオブジェクト指向クラスベース汎用並行
によって設計されたバートランドメイヤー
デベロッパーEiffelソフトウェア
初登場1986 [1]
安定リリース
EiffelStudio 20.11 [2] / 2020年12月21日; 14ヶ月前 (2020-12-21)
プレビューリリース
EiffelStudio 20.11 [3] / 2020年12月21日; 14ヶ月前 (2020-12-21)
規律の入力静的
実装言語エッフェル
プラットホームクロスプラットフォーム
OSFreeBSDLinuxMac OS XOpenBSDSolarisWindows
ライセンスデュアルおよびエンタープライズ
ファイル名拡張子.e
Webサイトwww .eiffel .org
主な実装
EiffelStudioLibertyEiffelSmartEiffelVisual Eiffel、Gobo Eiffel、「TheEiffelCompiler」tecomp
に影響を受けた
AdaSimulaZ
影響を受ける
Ada 2012AlbatrossC#DJavaRacketRuby[4] SatherScala

Eiffelは、Bertrand Meyer(オブジェクト指向の支持者であり、Object-Oriented Software Constructionの作成者)とEiffelSoftwareによって設計されたオブジェクト指向 プログラミング言語です。Meyerは、商用ソフトウェア開発の信頼性を高めることを目的として、1985年にこの言語を考案しました。[5]最初のバージョンは1986年に利用可能になりました。2005年に、EiffelはISO標準化された言語になりました。

言語の設計は、エッフェルプログラミング法と密接に関連しています。どちらも、契約による設計コマンドクエリの分離均一アクセスの原則単一選択の原則開放閉鎖原則オプションとオペランドの分離など、一連の原則に基づいています

Eiffelによって最初に導入された多くの概念は、後にJavaC#、およびその他の言語に取り入れられました。[要出典]特にEcma / ISO標準化プロセスを通じた新しい言語設計のアイデアは、引き続きEiffel言語に組み込まれています。

特徴

エッフェル語の主な特徴は次のとおりです。

  • クラスが分解の基本単位として機能するオブジェクト指向プログラム構造。
  • 他の言語構造と緊密に統合された契約による設計。
  • 自動メモリ管理。通常、ガベージコレクションによって実装されます。
  • 継承には、多重継承、名前の変更再定義、「選択」、不適合継承、および継承を安全にすることを目的としたその他のメカニズムが含まれます。
  • 制約付きおよび制約なしのジェネリックプログラミング
  • INTEGERなどの基本型を含むすべての型がクラスベースである、値と参照の両方のセマンティクスを処理する統一型システム。
  • 静的型付け
  • アタッチされたタイプのメカニズムによる、無効な安全性、またはnull参照の呼び出しに対する静的な保護。
  • クロージャラムダ計算に密接に関連するエージェント、または計算をラップするオブジェクト
  • オブジェクト共有と分散型初期化のために、一度ルーチン、またはルーチンが一度だけ評価されます。
  • ALGOL / Pascalの伝統におけるキーワードベースの構文ですが、セミコロンがオプションである限り、区切り記号はなく、ルーチンで演算子構文を使用できます。
  • 大文字と小文字の区別
  • Simple Concurrent Object-Oriented Programming(SCOOP)は、これらのビークルの特定の詳細(特定のミューテックス管理のない複数のスレッドなど)を超える抽象化レベルで、複数の同時にアクティブな実行ビークルの作成を容易にします。

設計目標

Eiffelは、手続き型コードよりも宣言型ステートメントを強調し、簿記の指示の必要性を排除しようとしています。

Eiffelは、コンパイラへの最適化のヒントとして意図されたコーディングトリックやコーディング手法を避けます。目的は、コードを読みやすくするだけでなく、プログラマーが実装の詳細にとらわれることなく、プログラムの重要な側面に集中できるようにすることです。Eiffelの単純さは、コンピューティングの問題に対する単純で、拡張可能で、再利用可能で、信頼できる答えを促進することを目的としています。Eiffelで記述されたコンピュータープログラム用のコンパイラーは、自動インライン化などの広範な最適化手法を提供し、プログラマーが最適化の負担の一部を軽減します。

背景

Eiffelは元々、BertrandMeyerによって設立された会社であるEiffelSoftwareによって開発されました。オブジェクト指向ソフトウェアの構築には、エッフェルの設計につながったオブジェクト技術の概念と理論の詳細な取り扱いが含まれています。[6]

Eiffel言語、ライブラリ、およびプログラミング方法の背後にある設計目標は、プログラマーが信頼性が高く、再利用可能なソフトウェアモジュールを作成できるようにすることです。Eiffelは、多重継承汎用性、ポリモーフィズムカプセル化、タイプセーフ変換、およびパラメーター共分散をサポートします。ソフトウェアエンジニアリングに対するEiffelの最も重要な貢献、契約による設計(DbC)です。この契約では、アサーション前提条件事後条件、およびクラス不変条件を使用して、効率を犠牲にすることなくプログラムの正確性を確保します。

Eiffelの設計は、オブジェクト指向プログラミング理論に基づいており、他のパラダイムの影響やレガシーコードのサポートへの懸念はわずかです。Eiffelは、抽象データ型を正式にサポートしています。Eiffelの設計では、ソフトウェアテキストは、「抽象データ型」の形式化された実装を使用して、テキスト自体から設計ドキュメントを再現できる必要があります。

実装と環境

EiffelStudioは、オープンソースまたは商用ライセンスのいずれかで利用できる統合開発環境です。ソフトウェアエンジニアリングのためのオブジェクト指向環境を提供しますEiffelEnvisionは、 Microsoft Visual Studioのプラグインであり、ユーザーがMicrosoft Visual Studio IDE内からEiffelプロジェクトを編集、コンパイル、およびデバッグできるようにします。他に5つのオープンソース実装が利用可能です。「TheEiffelCompiler」tecomp。ゴボエッフェル; SmartEiffel、古いバージョンの言語に基づくGNU実装。SmartEiffelコンパイラに基づくLibertyEiffel。ビジュアルエッフェル

他のいくつかのプログラミング言語には、Eiffelで最初に導入された要素が組み込まれています。たとえば、 Satherは元々Eiffelに基づいていましたが、その後分岐し、現在はいくつかの関数型プログラミング機能が含まれています。BlueJの前身であるインタラクティブな教育言語BlueもEiffelベースです。Apple Media Toolには、Eiffelベース のApple MediaLanguageが含まれています。

仕様と規格

Eiffel言語の定義は、ISOの国際標準です。この規格は、2005年6月21日に標準ECMA-367、Eiffel:Analysis、Design and ProgrammingLanguageとして最初に承認されたECMAInternationalによって開発されました。2006年6月、ECMAとISOは2番目のバージョンを採用しました。2006年11月、ISOは最初にそのバージョンを公開しました。この規格は、ECMAサイトで無料で見つけて使用できます。[7] ISOバージョン[8]は、フォーマットを除いてすべての点で同一です。

Eiffel Software、「The EiffelCompiler」tecompおよびEiffel-library-developerGoboは、標準の実装に取り​​組んでいます。EiffelSoftwareのEiffelStudio6.1および「EiffelCompiler」tecompは、主要な新しいメカニズムのいくつかを実装しています。特に、インラインエージェント、アサイナコマンド、角かっこ表記、不適合な継承、およびアタッチされたタイプです。SmartEiffelチームは、この標準から離れて独自のバージョンの言語を作成しました。これは、Eiffelの元のスタイルに近いと彼らは信じています。Object Toolsは、Eiffelコンパイラの将来のバージョンが標準に準拠するかどうかを明らかにしていません。LibertyEiffelは、 SmartEiffel言語と標準の 間のどこかに方言を実装します。

この規格は、次の先行するEiffel言語仕様を引用しています。

  • Bertrand Meyer:Eiffel:The Language、Prentice Hall、2回目の印刷、1992年(最初の印刷:1991年)
  • Bertrand Meyer:Standard Eiffel(前のエントリの改訂)、進行中、1997年から現在、Bertrand MeyerのETL3ページ、および
  • Bertrand Meyer:Object-Oriented Software Construction、Prentice Hall:初版、1988; 1997年第2版。
  • Bertrand Meyer:Touch of Class:オブジェクトと契約をうまくプログラムする方法を学ぶ、Springer-Verlag、2009 ISBN  978-3-540-92144-8 lxiv + 876ページフルカラー印刷、多数のカラー写真

2006年6月の標準の現在のバージョンには、いくつかの不整合が含まれています(たとえば、共変の再定義)[要出典]ECMA委員会は、不整合を解決する方法に関するタイムラインと方向性をまだ発表していません。

構文とセマンティクス

全体の構造

Eiffelの「システム」または「プログラム」はクラスのコレクションです。クラスのレベルより上で、Eiffelはクラスターを定義します。クラスターは本質的にクラスのグループであり、場合によってはサブクラスター(ネストされたクラスター)のグループです。クラスターは構文言語の構成ではなく、標準的な組織の規則です。通常、Eiffelプログラムは、各クラスが個別のファイルに編成され、各クラスターがクラスファイルを含むディレクトリに編成されます。この組織では、サブクラスターはサブディレクトリです。たとえば、標準の組織および大文字小文字の規則でx.eは、Xというクラスを定義するファイルの名前である可能性があります。

クラスには、他のオブジェクト指向プログラミング言語の「ルーチン」、「メンバー」、「属性」、または「メソッド」に類似した機能が含まれています。クラスはその不変条件も定義し、ドキュメントやメタデータの「メモ」セクションなどの他のプロパティを含みます。INTEGER、、STRINGなどのEiffelの標準データ型は、ARRAYすべてそれ自体がクラスです。

すべてのシステムには、「ルート」として指定されたクラスが必要であり、その作成プロシージャの1つが「ルートプロシージャ」として指定されています。システムの実行は、ルートクラスのインスタンスの作成とそのルートプロシージャの実行で構成されます。通常、これを行うと、新しいオブジェクトが作成されたり、新しい機能が呼び出されたりします。

Eiffelには、割り当て、オブジェクト作成、ルーチン呼び出し、条件、反復の5つの基本的な実行可能命令があります。Eiffelの制御構造は、構造化プログラミングの実施において厳密です。すべてのブロックには、正確に1つのエントリと1つの出口があります。

スコープ

多くのオブジェクト指向言語とは異なりますが、Smalltalkと同様に、Eiffelは、情報隠蔽またはデータ抽象化の原則の実用的なアプリケーションであり、データの正式なインターフェイスを必要とするオブジェクトの機能内を除いて、オブジェクトの属性への割り当てを許可しません。突然変異。他のオブジェクト指向プログラミング言語の言語にするには、すべてのEiffel属性が「保護」されており、クライアントオブジェクトが値を変更するには「セッター」が必要です。この結果、「セッター」は、Eiffelが構文を提供する不変条件を実装でき、通常は実装できます。

Eiffelは、クラスのクライアントによるクラスの機能への直接アクセスを許可しませんが、次のような「アサイナコマンド」の定義を許可します。

 
   some_attribute  SOME_TYPEはset_some_attribute を割り当て ます
    
   set_some_attribute  v  VALUE_TYPE 
                -some_attributeの値を `v 'に設定します。
            some_attribute := vendを実行し
                ます  
            

直接アクセスのように見えるものを許可するために開発者コミュニティ全体に少しお辞儀をしますが(たとえば、情報隠蔽の原則を破る)、使用されている「セッター」の現実を隠したり曖昧にしたりするため、この慣習は危険です。some_attribute実際には、上記のサンプルコードのように機能への直接アクセスを暗示するよりも、呼び出しをセッターにリダイレクトする方が適切です。[要出典]

「パブリック」、「プロテクト」、「プライベート」などの概念を持つ他の言語とは異なり、Eiffelはエクスポートテクノロジを使用して、クライアントクラスとサプライヤクラス間のスコープをより正確に制御します。機能の可視性は、コンパイル時に静的にチェックされます。たとえば、(以下)、「{NONE}」は他の言語の「保護された」に似ています。この方法で「機能セット」に適用されるスコープ(たとえば、「feature」キーワードの下から次の機能セットキーワードまたはクラスの終わりまで)は、「export」キーワードを使用して子孫クラスで変更できます。

feature  { NONE }  -初期化
	default_create-
			新しい「ゼロ」10進インスタンスを初期化します。
		make_zeroendを実行し
			ます
		

あるいは、{x}エクスポート宣言がないことは、{ANY}を意味し、他の言語の「パブリック」スコープに似ています。

機能 -定数

最後に、スコープは、次のようなEiffelプロジェクトユニバースの任意のクラスに対して選択的かつ正確に制御できます。

機能 { DECIMAL  DCM_MA_DECIMAL_PARSER  DCM_MA_DECIMAL_HANDLER }  -アクセス

ここで、コンパイラは、中括弧の間にリストされているクラスのみが機能グループ内の機能にアクセスできるようにします(たとえば、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コンパイラは、さまざまなレベルの機能とクラスのコントラクトを含めるように設計されています。たとえば、EiffelStudioは、「ワークベンチモード」での実行中に、すべての機能とクラスのコントラクトを実行します。実行可能ファイルが作成されると、コンパイラはプロジェクト設定ファイル(ECFファイルなど)を介して、コントラクトのセットを含めるか除外するかを指示されます。したがって、実行可能ファイルをコンパイルして、任意のレベルの契約を含めるか除外することができます。これにより、継続的なレベルのユニットテストと統合テストが実現します。さらに、EiffelStudioにある自動テスト機能を使用して、契約を継続的かつ系統的に行使することができます。

契約による設計メカニズムは、言語と緊密に統合されており、継承における機能の再定義をガイドします。

  • 日常的な前提条件:前提条件は、継承によってのみ弱めることができます。祖先の要件を満たすすべての呼び出しは、子孫の要件を満たします。
  • 日常的な事後条件:事後条件は、継承によってのみ強化できます。祖先によって保証された結果は、引き続き子孫によって提供されます。
  • クラス不変:オブジェクトの作成後、およびエクスポートされたクラスルーチンの呼び出し後にtrueを保持する必要がある条件。不変条件は頻繁にチェックされるため、同時に最も高価で最も強力な条件または契約の形式になります。

さらに、この言語は「チェック命令」(一種の「アサート」)、ループ不変条件、およびループバリアント(ループ終了を保証する)をサポートしています。

ボイドセーフ機能

静的型付けのようなボイドセーフ機能は、ソフトウェアの品質を向上させるためのもう1つの機能です。ボイドセーフソフトウェアは、ボイド参照の呼び出しによって引き起こされる実行時エラーから保護されているため、ボイドターゲットへの呼び出しが発生する可能性のあるソフトウェアよりも信頼性が高くなります。静的型付けとの類似性は有用なものです。実際、ボイドセーフ機能は型システムの拡張、または静的型付けを超えたステップと見なすことができます。これは、ボイドセーフを保証するメカニズムが型システムに統合されているためです。

無効なターゲット呼び出しに対するガードは、アタッチメントおよび(拡張により)デタッチメント(たとえば、デタッチ可能キーワード)の概念によって見ることができます。ボイドセーフ機能は、上記で使用したサンプルコードの短い手直しで見ることができます。

   some_attribute  取り外し可能な SOME_TYPE
    
   use_some_attribute 
                -some_attributeの値を `v 'に設定します。
            some_attribute
                l_attributeとしてアタッチされている場合 do_something l_attribute end end    
                     
                
            
    
    do_something  a_value  SOME_TYPE 
                -`a_value 'で何かをします。
            do 
               ...  ` a_value 'で何か する ... end  
            

上記のコード例は、コンパイラが、some_attribute使用された時点でアタッチされるかデタッチされるかという信頼性に静的に対処する方法を示しています。特に、このattachedキーワードは「添付ファイルローカル」(例l_attribute)を許可します。これは、ifステートメント構造で囲まれたコードのブロックのみにスコープされます。したがって、この小さなコードブロック内で、ローカル変数(eg l_attribute)が非void(つまり、void safe)であることが静的に保証されます。

機能:コマンドとクエリ

クラスの主な特徴は、機能のセットを定義することです。クラスは実行時オブジェクトのセット、つまり「インスタンス」を表すため、機能はこれらのオブジェクトに対する操作です。機能には、クエリとコマンドの2種類があります。クエリは、インスタンスに関する情報を提供します。コマンドはインスタンスを変更します。

コマンドクエリの区別は、エッフェル塔の方法にとって重要です。特に:

  • 統一アクセスの原則:クラス機能を呼び出すソフトウェアクライアントの観点からは、クエリが属性(フィールド値)であるか関数(計算値)であるかによって違いはありません。たとえばa_vehicle.speed、オブジェクトでアクセスされる属性である場合a_vehicleもあれば、距離を時間で除算する関数によって計算される場合もあります。どちらの場合も表記は同じであるため、クライアントソフトウェアに影響を与えることなく、クラスの実装を簡単に変更できます。
  • コマンドクエリ分離の原則:クエリはインスタンスを変更してはなりません。これは言語のルールではなく、方法論の原則です。したがって、優れたEiffelスタイルでは、何かを変更して結果を返す「get」関数は見つかりません。代わりに、オブジェクトを変更するためのコマンド(手順)と、先行する変更の結果としてオブジェクトに関する情報を取得するためのクエリがあります。

オーバーロード

Eiffelは引数のオーバーロードを許可しませんクラス内の各機能名は、常にクラス内の特定の機能にマップされます。1つのクラス内の1つの名前は、1つのことを意味します。この設計上の選択は、呼び出しによって呼び出されるルーチンに関するあいまいさの原因を回避することにより、クラスの可読性を向上させます。また、言語メカニズムを簡素化します。特に、これがエッフェルの多重継承メカニズムを可能にするものです。[9]

もちろん、名前はさまざまなクラスで再利用できます。たとえば、機能plus(およびそのインフィックスエイリアス"+" )は、 INTEGERREALSTRINGなど のいくつかのクラスで定義されています。

寛大さ

汎用クラスは、タイプによって異なるクラスです(たとえば、LIST [PHONE]、電話番号のリスト、ACCOUNT [G-> ACCOUNT_TYPE]、ACCOUNT [SAVINGS]およびACCOUNT [CHECKING]など)。クラスは、型によってパラメーター化されていることを表すために、ジェネリックにすることができます。一般的なパラメーターは角括弧内に表示されます。

クラス LIST  [ G ]  ..。

Gは「正式なジェネリックパラメーター」として知られています。(Eiffelはルーチン用に「引数」を予約し、ジェネリッククラスにのみ「パラメーター」を使用します。)このような宣言では、Gはクラス内で任意の型を表します。したがって、関数はタイプGの値を返すことができ、ルーチンはそのタイプの引数を取ることができます。

item  G  do  ...  end 
put  x  G  do  ...  end

LIST [INTEGER]およびは、このクラスLIST [WORD]「ジェネリック派生」です。許可される組み合わせ(、、、、n: INTEGERは次 w: WORDのとおりil: LIST [INTEGER]です。wl: LIST [WORD]

n  :=  il アイテム
wl put  w 

INTEGERおよびWORDは、これらのジェネリック派生の「実際のジェネリックパラメーター」です。

また、「制約付き」の仮パラメータを設定することもできます。この場合、実際のパラメータは、特定のクラス「制約」から継承する必要があります。たとえば、

   クラス HASH_TABLE  [ G  KEY- > HASHABLE  ] 

派生は、から継承するHASH_TABLE [INTEGER, STRING]場合にのみ有効です(通常のEiffelライブラリで実際にそうであるように)。クラス内で、によって制約されているということは、のように、のすべての機能に適用できることを意味しますSTRINGHASHABLEKEYHASHABLEx: KEYxHASHABLEx.hash_code

継承の基本

1つまたは複数の他のクラスから継承するために、クラスinheritの先頭に句 が含まれます。

クラス Cは ABを継承
   します
   

--...残りのクラス宣言..。

クラスは、継承された機能の一部またはすべてを再定義(オーバーライド)する場合があります。redefineこれは、クラスの開始時に、次のように、継承句の副節を 介して明示的に通知する必要があります。

クラス C 継承
    A
        再定義 f  g  h 終了
    B
        再定義 u  v 終了

Eiffelの継承の詳細については、 [10]を参照してください。

延期されたクラスと機能

クラスは、クラスが直接インスタンス化されない可能性があることを示すために、deferred classではなくで定義される場合があります。classインスタンス化できないクラスは、他のオブジェクト指向プログラミング言語では抽象クラスと呼ばれます。Eiffelの用語では、「有効な」クラスのみをインスタンス化できます(遅延クラスの子孫である可能性があります)。deferredの代わりにキーワードを使用して、機能を延期することもできます。doクラスに遅延機能がある場合は、遅延として宣言する必要があります。ただし、遅延機能のないクラスは、それでもそれ自体が遅延される可能性があります。

多くのオブジェクト指向プログラミング理論家は、インターフェース自体がJavaの多重継承の欠如(Eiffelが持っている)に対する答えであると信じていますが、遅延クラスはJavaなどの言語のインターフェースと同じ役割を果たします。[11] [12]

名前の変更

1つ以上の他のクラスから継承するクラスは、デフォルトで元の名前ですべての機能を取得します。ただし、rename句を介して名前を変更する場合があります。これは、継承された機能間に名前の衝突がある場合に多重継承の場合に必要です。名前を変更しないと、結果のクラスは上記のオーバーロードなしの原則に違反するため、無効になります。

タプル

タプルタイプは、属性と対応する「セッター」プロシージャのみを提供する、クラスの単純な形式と見なすことができます。典型的なタプルタイプは

   タプル [名前 文字列;  重量 REAL ;  日付 DATE ]

クラスが必要ない場合は、出生記録の単純な概念を説明するために使用できます。このようなタプルのインスタンスは、次のように角かっこで囲まれた、指定されたタイプの値のシーケンスです。

   [ "ブリジット"  3.5  Last_night ]

このようなタプルのコンポーネントには、タプルタグがクラスの属性であるかのようにアクセスできます。たとえばt、上記のタプルが割り当てられている場合、t.weight値は3.5になります。

アサイナコマンドの概念(以下を参照)のおかげで、ドット表記を使用して、次のようにそのようなタプルのコンポーネントを割り当てることもできます。

   t 重量 :=  t 重量 +0.5  _

タプルタグはオプションであるため、タプルタイプをとして記述することもできTUPLE [STRING, REAL, DATE]ます。(一部のコンパイラでは、タグがECMA標準で導入されたため、これがタプルの唯一の形式です。)

たとえば、の正確な仕様は、少なくとも3つの要素TUPLE [A, B, C]のシーケンスを記述し、最初の3つはそれぞれタイプ、、であるということです。その結果、すべてのタプルタイプが準拠する最上位のタプルタイプに 準拠します(割り当てられる場合があります)、toおよびto (パラメータなし)。ABCTUPLE [A, B, C]TUPLE [A, B]TUPLE [A]TUPLE

エージェント

Eiffelの「エージェント」メカニズムは、操作をオブジェクトにラップします。このメカニズムは、反復、イベント駆動型プログラミング、およびプログラム構造の周りで操作を渡すことが役立つその他のコンテキストに使用できます。他のプログラミング言語、特に関数型プログラミングを強調する言語では、継続クロージャ、またはジェネレーターを使用して同様のパターンを使用できます。Eiffelのエージェントは、言語のオブジェクト指向パラダイムを強調し、SmalltalkおよびRubyのコードブロックと同様の構文とセマンティクスを使用します。

たとえば、my_actionの各要素のブロックを実行するにはmy_list、次のように記述します。

   my_list do_all  エージェント my_action 

my_actionを満たす要素に対してのみ実行するためmy_conditionに、制限/フィルターを追加できます。

   my_list do_if  エージェント my_action  エージェント my_condition 

これらの例では、my_actionおよびmy_conditionはルーチンです。それらの前に接頭辞を付けるとagent、対応するルーチンとそのすべてのプロパティ、特に適切な引数で呼び出される機能を表すオブジェクトが生成されます。したがって、ifaがそのオブジェクトを表す場合(たとえば、aがへの引数であるためdo_all)、命令

   _ 呼び出し [ x ] 

x元のルーチンを直接呼び出したかのように、引数を使用して元のルーチンを呼び出しますmy_action (x)の引数callは、ここではタプルとして渡されます[x]

エージェントへのいくつかの引数を開いたままにし、他の引数を閉じたままにすることができます。開いている引数は、次の引数として渡されます。エージェントの使用call時に提供されます閉じた引数は、エージェント定義時に提供されますたとえば、引数が2つある場合、反復 action2

   my_list do_all  エージェント action2   y ))

action2 (x, y)の連続する値を繰り返しますx。2番目の引数は。に設定されたまま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 ( ' ' 確実追加s .count  = old s .count + 1 end 
     
               
     

ここで渡されるインラインエージェントは、事前条件、事後条件、レスキュー句(ここでは使用されません)、および完全な署名を含む、通常のルーチンのすべてのトラップを持つことができます。これにより、必要なのがエージェントでラップされる計算だけである場合に、ルーチンを定義する必要がなくなります。これは、リストのすべての要素が正であることを表す不変句のように、特にコントラクトに役立ちます。

   my_list for_all  agent  x  INTEGER ): BOOLEAN  do  Result  :=  x  >  0  end 

現在のエージェントメカニズムでは、実行時型エラーの可能性があります(n個の引数を持つルーチンがm < nm個の引数を期待するエージェントに渡された場合)。これは、の前提条件による実行時チェックによって回避できますRibet et al。による言語変更の提案を含む、この問題の純粋に静的な修正のためのいくつかの提案が利用可能です。[13]valid_argumentscall

一度ルーチン

onceルーチンの結果は、の代わりにキーワードを使用してキャッシュできますdoルーチンへの最初以外の呼び出しは、追加の計算やリソース割り当てを必要としませんが、以前に計算された結果を返すだけです。「oncefunctions」の一般的なパターンは、共有オブジェクトを提供することです。最初の呼び出しでオブジェクトが作成され、後続の呼び出しでそのオブジェクトへの参照が返されます。典型的なスキームは次のとおりです。

shared_object  SOME_TYPE
    は一度
        Resultを作成します make args -これにより、オブジェクトが作成され、 `Result 'を介してオブジェクトへの参照が返されます。終わり 
             
    

返されるオブジェクトResult(例では)自体は変更可能ですが、その参照は同じままです。

多くの場合、「1回のルーチン」は必要な初期化を実行します。ライブラリへの複数の呼び出しには初期化プロシージャの呼び出しを含めることができますが、最初のそのような呼び出しのみが必要なアクションを実行します。このパターンの初期化を使用すると、分散化でき、特別な初期化モジュールの必要性を回避できます。「Onceルーチン」は、目的と効果が多くのプログラミング言語のシングルトンパターン、およびPythonで使用される Borgパターンに似ています。

デフォルトでは、「1回のルーチン」はスレッドごとに1回呼び出されます。セマンティクスは、「1回のキー」で修飾することにより、プロセスごとに1回、またはオブジェクトごとに1回に調整できますonce ("PROCESS")

コンバージョン

Eiffelは、さまざまなタイプ間の変換を可能にするメカニズムを提供します。メカニズムは継承と共存し、それを補完します。2つのメカニズム間の混乱を避けるために、設計では次の原則が適用されます。

(変換の原則)タイプは、適合と別のタイプへの変換の両方を行うことはできません。

たとえば、にNEWSPAPER準拠する場合がありますPUBLICATIONが、にINTEGER変換されますREAL(継承されません)。

変換メカニズムは、ほとんどのプログラミング言語に存在するアドホック変換ルール(実際にはとの間INTEGERなどREAL)を単純に一般化し、上記の原則が守られている限り、どのタイプにも適用できるようにします。たとえば、クラスを;DATEに変換するように宣言できます。STRINGこれにより、日付から文字列を簡単に作成できます。

   my_string  :=  my_date

変換手順で明示的なオブジェクト作成を使用するためのショートカットとして:

    my_stringを作成しますmake_from_date  my_date 

make_from_date最初のフォームを2番目のフォームの同義語として使用できるようにするには、クラスの先頭のconvert句に 作成手順(コンストラクター)をリストするだけで十分です。

別の例として、からリストされているそのような変換手順がある場合TUPLE [day: INTEGER; month: STRING; year: INTEGER]、タプルを日付に直接割り当てて、次のように適切な変換を行うことができます。

      Bastille_day  :=  [ 14  "7月"  1789 ]

例外処理

Eiffelでの例外処理は、契約による設計の原則に基づいています。たとえば、ルーチンの呼び出し元が前提条件を満たさない場合、またはルーチンが約束された事後条件を保証できない場合、例外が発生します。Eiffelでは、例外処理は制御フローやデータ入力ミスの修正には使用されません。

Eiffel例外ハンドラーは、rescueキーワードを使用して定義されます。レスキューセクション内で、 retryキーワードはルーチンを再実行します。たとえば、次のルーチンは、ルーチンの実行の試行回数を追跡し、特定の回数だけ再試行します。

connect_to_server  server  SOCKET 
      -サーバーに接続するか、10回試行した後にあきらめます。
    server / = Void 、次にserverが必要です
        アドレス/ =無効なローカル試行INTEGER doserver 接続する接続を確認するサーバーis_connectedレスキュー試行回数が10未満の場合試行回数:=試行回数+1試行終了終了      
    
         
    
        
    
       
    
            
                
            
        
    

ただし、この例は、接続障害が予想されるため、最も単純なプログラム以外では間違いなく欠陥があります。ほとんどのプログラムでは、attempt_connecting_to_serverのようなルーチン名の方が適切であり、事後条件では接続が約束されないため、接続が開かれなかった場合は、呼び出し元が適切な手順を実行する必要があります。

並行性

EiffelNetやEiffelThreadsなど、多数のネットワークおよびスレッドライブラリを利用できます。契約による設計の概念に基づくEiffelの並行性モデルは、SCOOP、つまりSimple Concurrent Object-Oriented Programmingであり、まだ公用語の定義には含まれていませんが、EiffelStudioで利用できます。CAMEO [14]は、エッフェル塔のSCOOPの(実装されていない)バリエーションです。並行性も例外と相互作用します。非同期例外は厄介な場合があります(呼び出し元が終了した後にルーチンが例外を発生させる場合)。[15]

演算子とブラケットの構文、割り当てコマンド

エッフェルの計算の見方は、すべての操作がオブジェクト、つまり「ターゲット」に関連しているという意味で、完全にオブジェクト指向です。たとえば、次のような追加

a  +  b

概念的には、メソッド呼び出しであるかのように理解されます

_ プラス b 

ターゲットa、機能plus、引数を使用しますb

もちろん、前者は従来の構文であり、通常は好まれます。演算子構文を使用すると、機能を宣言することでどちらの形式も使用できます(たとえば、INTEGERで、これは他の基本クラスに適用され、そのような演算子が適切な他のクラスで使用できます)。

プラス エイリアス "+"  その他 INTEGER ): INTEGER -...
        通常の関数宣言...
    終了

「エイリアス」として使用できる演算子の範囲は非常に広いです。これらには、「+」などの事前定義された演算子だけでなく、英数字以外の記号で作成された「フリー演算子」も含まれます。これにより、たとえば数学や物理学のアプリケーションで、特別な中置および接頭辞表記を設計することが可能になります。

さらに、すべてのクラスには、「[]」にエイリアスされた1つの関数、「ブラケット」演算子があり、選択された関数がどこにあるかa [i, ...]の同義語として表記できます。これは、配列、ハッシュテーブル、リストなどのコンテナ構造に特に役立ちます。たとえば、文字列キーを使用したハッシュテーブルの要素へのアクセスを記述できます。 a.f (i, ...)f

   番号 :=  phone_book  [ "JILL SMITH" ]

「アサイナコマンド」は、オブジェクト指向プログラミングのフレームワークで再解釈された、確立された便利な表記を可能にするという同じ精神で設計されたコンパニオンメカニズムです。アサイナコマンドを使用すると、代入のような構文で「セッター」プロシージャを呼び出すことができます。a.x := vこれは情報隠蔽に違反するため、適切な割り当てを形式にすることはできません。セッターコマンド(手順)を実行する必要があります。たとえば、ハッシュテーブルクラスは関数とプロシージャを持つことができます

アイテム エイリアス "[]"  キー STRING ): ELEMENT          [ 3 ] 
      -キー `key 'の要素。
      -( "Getter"クエリ)
    do 
        ... 
    end

put  e  ELEMENT ;  key  STRING 
      -要素 `e 'を挿入し、キー` key'に関連付けます。
      -(「セッター」コマンド)
    do 
        ... 
    end

次に、要素を挿入するには、setterコマンドの明示的な呼び出しを使用する必要があります。

   [ 4 ]  phone_book put  New_person  "JILL SMITH" 

これは次のように同等に書くことができます

   [ 5 ]  phone_book  [ "JILL SMITH" ]  :=  New_person

phone_book ["JILL SMITH"](の同義語であるのと同じように)、ただし、 now start([3]の置換 number := phone_book.item ("JILL SMITH"))の宣言がitem

   アイテム エイリアス "[]"  キー STRING ): ELEMENT 割り当て プット

これは、ブラケットエイリアスと組み合わせて[5]を有効にし、[4]と同等にするputアサイナコマンドとして宣言します。item(角かっこを利用せずに、のように書くこともできますphone_book.item ("JILL SMITH") := New_person

注:aの割り当て者の引数リストは次のように制約されます:(aの戻り型;すべてのaの引数リスト...)

字句および構文のプロパティ

Eiffelでは大文字と小文字は区別されません。トークンmakemaKeおよびMAKEすべてが同じ識別子を示します。ただし、以下の「スタイルルール」を参照してください。

コメントは--(2つの連続したダッシュ)によって導入され、行の終わりまで拡張されます。

命令区切り文字としてのセミコロンはオプションです。1行の複数の命令を区切る場合を除いて、ほとんどの場合、セミコロンは省略されます。これにより、プログラムページがすっきりします。

機能宣言とクラス宣言のネストはありません。その結果、Eiffelクラスの構造は単純です。いくつかのクラスレベルの句(継承、不変)と一連の機能宣言がすべて同じレベルにあります。

読みやすくするために、機能を個別の「機能句」にグループ化するのが通例です。たとえば、基本機能タグの標準セットが標準の順序で表示されます。

クラス HASH_TABLE  [ ELEMENT  KEY- > HASHABLE  ]継承TABLE [ ELEMENT ]    

    機能 -初期化-...
         初期化コマンド(作成手順/コンストラクター)の宣言..。

    機能 -アクセス
         -...オブジェクトの状態に関する非ブールクエリの宣言(例:item .. ..

    機能 -ステータスレポート
         -...オブジェクトの状態に関するブールクエリの宣言(例:is_empty .. ..

    機能 -要素の変更-...
         構造を変更するコマンドの宣言(例:put .. ..

    -など
終了

ほとんどの中括弧プログラミング言語とは対照的に、Eiffelは式と命令を明確に区別します。これは、エッフェル法のコマンドクエリ分離の原則に沿ったものです。

スタイルの規則

Eiffelのドキュメントの多くは、一貫したルックアンドフィールを適用するように設計された独特のスタイル規則を使用しています。これらの規則の一部はコード形式自体に適用され、その他の規則は、これらの規則が可能な形式および出版物でのEiffelコードの標準的な活版印刷レンダリングに適用されます。

言語では大文字と小文字は区別されませんが、スタイル標準では、クラス名にすべて大文字(LIST)、機能名にすべて小文字(make)、定数に初期大文字()を使用することが規定されていますAvogadro推奨されるスタイルは、のように、マルチワード識別子のコンポーネントを区切るためのアンダースコアも提案しますaverage_temperature

Eiffelの仕様には、ソフトウェアテキストをタイプセット形式で表示するためのガイドラインが含まれています。太字のキーワード、ユーザー定義の識別子と定数はitalics、コメント、演算子、句読点で示され、Romanプログラムテキストblueは現在の記事のように示されています。説明文。たとえば、「He​​llo、world!」上記のプログラムは、Eiffelのドキュメントで次のようにレンダリングされます。

class 
    HELLO_WORLD 
create 
    make 
feature 
    make 
       do 
          print  "Hello、world!" 
       end 
end

他のツールや言語へのインターフェース

Eiffelは純粋にオブジェクト指向言語ですが、他のプログラミング言語の「外部」ソフトウェアとインターフェイスするため のオープンアーキテクチャを提供します。

たとえば、 Cでマシンレベルおよびオペレーティングシステムレベルの操作をプログラムすることができますEiffelは、「インラインC」(通常は短いマシンレベルの操作のためにEiffelルーチンの本体をCで記述する)のサポートを含む、Cルーチンへの簡単なインターフェイスを提供します。

EiffelとCの間に直接の接続はありませんが、多くのEiffelコンパイラVisual Eiffelは1つの例外です)は、最適化移植性のために、Cコンパイラに送信する中間言語としてCソースコードを出力します。そのため、これらはトランスコンパイラの例です。Eiffelコンパイラtecompは、中間Cコードを経由せずに(インタプリタのように)Eiffelコードを直接実行したり、最適化されたネイティブコードを取得するためにCコンパイラに渡されるCコードを出力したりできます。.NETでは、EiffelStudioコンパイラはCIL(共通中間言語)コードを直接生成します。SmartEiffel _コンパイラはJavaバイトコードを出力することもできます。

参考文献

  1. ^ 「一言で言えばエッフェル」archive.eiffel.com 2017年8月24日取得
  2. ^ 「EiffelStudio19.05が利用可能になりました!」Eiffel.org2020年12月22日。
  3. ^ 「EiffelStudio20.11リリース」Eiffel.org
  4. ^ クーパー、ピーター(2009)。Rubyの始まり:初心者からプロフェッショナルまで初心者からプロフェッショナルまで(第2版)。バークレー:APress。p。101. ISBN 978-1-4302-2363-4程度は低いですが、Python、LISP、Eiffel、Ada、およびC ++もRubyに影響を与えています。
  5. ^ 「エッフェル–言語」2016年7月6日取得
  6. ^ Object-Oriented Software Construction、Second Edition、by Bertrand Meyer、Prentice Hall、1997、 ISBN 0-13-629155-4 
  7. ^ ECMAインターナショナル:標準ECMA-367 – Eiffel:分析、設計、プログラミング言語第2版(2006年6月)。www.ecma-international.org/publications/standards/Ecma-367.htmからオンラインで入手可能
  8. ^ 国際標準化機構:標準ISO / IEC DIS 25436、 [1]でオンラインで入手可能
  9. ^ Bertrand Meyer:Overloading vs Object Technology、Journal of Object-Oriented Programming(JOOP)、vol。14、いいえ。2001年10月4日〜11月、オンラインで入手可能
  10. ^ 「9継承」Archive.eiffel.com。1997-03-23 2013年7月8日取得
  11. ^ 「多重継承とインターフェース」Artima.com。2002-12-16 2013年7月8日取得
  12. ^ 「多重継承は悪ではありません」C2.com。2007-04-28 2013年7月8日取得
  13. ^ Philippe Ribet、Cyril Adrian、Olivier ZendraDominique Colnet: Journal of Object Technology、vol。3、いいえ。4、2004年4月、特集:TOOLS USA 2003、pp.125-143。JOTの記事ページからオンラインで入手可能
  14. ^ ブルック、フィリップ; リチャードペイジ(2008)。「カメオ:エッフェル塔の並行性の代替モデル」(PDF)コンピューティングの正式な側面スプリンガー。21(4):363–391。土井10.1007 / s00165-008-0096-1S2CID18336088_  
  15. ^ ブルック、フィリップ; リチャードペイジ(2007)。「コンカレントエッフェルの例外」ジャーナルオブオブジェクトテクノロジー6(10):111–126。土井10.5381 /jot.2007.6.10.a4

外部リンク

  • Eiffelを紹介した会社のEiffelSoftware Webサイトは、Interactive Software Engineering(ISE)でした。