Ada では、タイプ T のプリミティブ操作は、T が定義されているパッケージでのみ定義できます。たとえば、Vehicules
パッケージがタグ付けされたレコードを定義Car
しBike
、両方とも共通のVehicle
抽象タグ付き型を継承している場合、クラス全体の型でディスパッチできるすべての操作をこのパッケージVehicle'Class
で定義する必要があります。Vehicles
プリミティブな操作を追加したくないとしましょう。ソース ファイルを編集する権限がないか、無関係な機能でパッケージを混乱させたくない場合です。
次に、 type で暗黙的にディスパッチする操作を他のパッケージで定義することはできませんVehicle'Class
。たとえば、車両をシリアル化する (ディスパッチ機能を使用してVehicles_XML
パッケージを定義するTo_Xml
) か、UI 要素として表示する (、、... ディスパッチ機能を使用してパッケージを定義する)Vehicles_GTK
などの場合があります。動的ディスパッチを実行する唯一の方法は、次のように記述することです。コードを明示的に; たとえば、内部:Get_Label
Get_Icon
Vechicle_XML
if V in Car'Class then
return Car_XML (Car (V));
else
if V in Bike'Class then
return Bike_XML (Bike (V));
else
raise Constraint_Error
with "Vehicle_XML is only defined for Car and Bike."
end if;
(そして、 で定義され、他の場所で使用されている Visitor パターンVehicles
はもちろん機能しますが、それでも同じ種類の明示的なディスパッチ コードが必要です。実際には、いいえ、しかしまだ書く定型コードがいくつかあります)
私の質問は次のとおりです。
T で動的にディスパッチする操作が T の定義パッケージで定義されるように制限されている理由はありますか?
これは意図的なものですか?これには何か歴史的な理由があるのでしょうか?
ありがとう
編集:
現在の回答に感謝します。基本的に、それは言語の実装(ルール/仮想テーブルの凍結)の問題のようです。
コンパイラは時間の経過とともに段階的に開発され、すべての機能が既存のツールにうまく適合するわけではないことに同意します。そのため、ディスパッチ オペレーターを独自のパッケージに分離することは、言語設計よりも既存の実装によって主に導かれる決定のようです。C++/Java ファミリ以外の言語は、そのような要件のない動的ディスパッチを提供します (たとえば、OCaml、Lisp (CLOS)。それが重要な場合、それらもコンパイル済み言語、またはより正確には、コンパイラが存在する言語です)。
この質問をしたとき、言語仕様レベルで、Ada 仕様のこの部分の背後にもっと根本的な理由があるかどうかを知りたかった (そうでなければ、仕様が動的ディスパッチの特定の実装を想定/強制することを本当に意味するのだろうか?)
理想的には、リファレンス マニュアルの理論的根拠やガイドラインセクション、言語のこの特定の部分に関するあらゆる種類のアーカイブされた議論など、信頼できる情報源を探しています。