パッケージのオプション
この章では、パッケージについて詳しく説明します。
永続クラスの場合は、パッケージが SQL スキーマとして SQL で表現されます。詳細は、このドキュメントで後述する “パッケージからスキーマへのプロジェクション” を参照してください。
Important:
パッケージ名が含まれていないクラスへの参照を InterSystems IRIS® が検出したときに、クラス名の先頭が “%” の場合、InterSystems IRIS は、そのクラスが “%Library” パッケージに含まれているものと見なします。
パッケージの概要
InterSystems IRIS は、特定のデータベース内の関連するクラスをグループ化するパッケージをサポートしています。パッケージには、以下の利点があります。
-
大規模なアプリケーションを構築し、他の開発者とコードを共有する簡単な方法を開発者に提供します。
-
クラス間で名前が衝突する問題を容易に回避できます。
-
オブジェクト・ディクショナリ内の SQL スキーマを、単純明快に表現する論理的な方法を提供します。つまり、1 つのパッケージが 1 つのスキーマに対応します。
パッケージは、関連するクラスを共通の名前の下に 1 つのグループとしてまとめる簡単な方法です。例えば、アプリケーションに “Accounting” システムと “Inventory” システムがあるとします。これらのアプリケーションを構成するクラスを、“Accounting” パッケージと “Inventory” パッケージに編成できます。
上記のクラスは、いずれも (パッケージ + クラス名から成る) フル・ネームを使用して参照されます。
Do ##class(Accounting.Invoice).Method()
Do ##class(Inventory.Item).Method()
パッケージ名がコンテキストから決定される場合は (下記参照)、パッケージ名を省略できます。
Do ##class(Invoice).Method()
クラスと同様に、パッケージ定義は、InterSystems IRIS データベース内に存在します。パッケージのデータベースからネームスペースへのマッピングの詳細は、“パッケージ・マッピング” のセクションを参照してください。
パッケージ名
パッケージ名は、文字列です。“.” (ピリオド) は使用できますが、その他の句読点は使用できません。パッケージ名のピリオドで区切られた各部は、1 つのサブパッケージであり、複数のサブパッケージが存在することもあります。あるクラスに Test.Subtest.TestClass と名前を付けた場合、パッケージ名は Test、サブパッケージ名は Subtest、クラス名は TestClass になります。
パッケージ名の長さと使用法には、以下のような制限があります。
-
パッケージ名は長さ制限に従います。"サーバ側プログラミングの入門ガイド" の "識別子のルールとガイドライン" にある “クラス” を参照してください。
-
1 つのネームスペース内では、各パッケージ名が一意になる必要があります (大文字と小文字は区別されません)。つまり、1 つのネームスペース内に “ABC” と “abc” というパッケージが同時に存在することはなく、“abc.def” というパッケージとサブパッケージは、“ABC” パッケージの一部として扱われるということです。
識別子に関する一般的な情報は、“クラスの定義とコンパイル” の章の “名前付け規約” を参照してください。
パッケージの定義
パッケージは、暗にクラス名の意味を含みます。クラスを作成すると、パッケージは自動的に定義されます。同様に、パッケージ内のクラスをすべて削除すると、そのパッケージも自動的に削除されます。
以下に、パッケージ名が Accounting でクラス名が Invoice、完全修飾クラス名が Accounting.Invoice の例を示します。
Class Accounting.Invoice
{
}
パッケージ・マッピング
定義では、各パッケージは、特定のデータベースに含まれます。しばしば、各データベースは、ネームスペースに関連付けられ、データベースとネームスペースは、共通の名前を共有します。データベース内のパッケージ定義をそのデータベースと関連付けられていないネームスペースで使用できるようにするには、パッケージ・マッピングを使用します。この手順については "システム管理ガイド" で詳しく説明していますが、以下に概要を示します。パッケージを格納しているデータベースがソース・データベースです。パッケージのマッピング先のネームスペースはターゲット・ネームスペースと呼びます。パッケージをマップする手順は以下のとおりです。
-
管理ポータルのホーム・ページで、[ネームスペース] ページ ([システム管理]→[構成]→[システム構成]→[ネームスペース]) に移動します。
-
[ネームスペース] ページで、テーブル内の対応する行にある [パッケージ・マッピング] をクリックして、ターゲット・ネームスペースを選択します。ターゲット・ネームスペースの [パッケージ・マッピング] ページが表示されます。
-
[パッケージ・マッピング] ページで、[新規] をクリックします。これによって、マッピング設定のダイアログが表示されます。
-
このダイアログで、以下のようにフィールドに情報を入力します。
[OK] をクリックするとこれらの値が使用され、ダイアログが閉じます。
-
[パッケージ・マッピング] ページにマッピングが表示されます。[変更を保存] をクリックし、マッピングを保存します。
パッケージをネームスペースを超えてマップすると、パッケージの定義はマップされますが、そのデータはマップされません。
Important:
パッケージをマップするときには、そのパッケージ内のクラスが必要とするすべてのコードとデータを特定して、そのすべてのコードとデータがすべてのターゲット・ネームスペースで使用できることを必ず確認します。マップされるクラスは、以下の項目に依存している可能性があります。
-
インクルード・ファイル
-
ルーチン
-
その他のクラス
-
テーブル
-
グローバル
追加のルーチン、パッケージ、およびグローバル・マッピングを必要に応じて使用して、これらの項目がターゲット・ネームスペースで使用できるようにします。"システム管理ガイド" の “ネームスペースの構成” の章にある “ネームスペースへのグローバル、ルーチン、およびパッケージ・マッピングの追加” を参照してください。
パッケージをマップすると、そのパッケージのクラス定義と、同じパッケージ内の生成されたルーチンにマッピングが適用されます。
複数のネームスペースにわたるパッケージのマッピング
InterSystems IRIS は、1 つの動作で複数のターゲット・ネームスペースにわたって同じソース・パッケージを使用できるようにする機能を備えています。
パッケージを複数のネームスペースで使用可能にする手順は以下のとおりです。
-
"システム管理ガイド" の “InterSystems IRIS の構成” の章にある “ネームスペースの作成” の説明に従い、%ALL というネームスペースを作成します。
-
このセクションの説明に従ってパッケージのマッピングを作成し、保存します。
マッピングしたパッケージのクラスが、%SYS ネームスペース、USER ネームスペース、および任意のユーザ定義ネームスペースで認識でき、使用可能になります。
Note:
%ALL ネームスペースを削除すると、そのマッピングが削除されます。
クラス参照時のパッケージの使用
クラスの参照には、2 つの方法があります。
-
完全修飾された名前 (すなわち、Package.Class) を使用します。例えば、以下のようになります。
// create an instance of Lab.Patient
Set patient = ##class(Lab.Patient).%New()
-
短いクラス名を使用し、クラスがいずれのパッケージに属するのかをクラス・コンパイラに解決させます。
既定では、短いクラス名を使用すると、InterSystems IRIS はそのクラスを、使用しているコードを含むクラスのパッケージ (存在する場合)、%Library パッケージ、または User パッケージのいずれかに含まれるクラスであると見なします。
コンパイラで別のパッケージのクラスを検索する場合は、次のセクションで説明するように、それらのパッケージをインポートします。
Note:
不明確な短いクラス名を使用するとエラーになります。つまり、2 つ以上のパッケージに同じ短いクラス名が付いていて、そのパッケージすべてをインポートする場合、コンパイラがパッケージ名を解決する時点でエラーになります。このようなエラーを避けるためにフル・ネームを使用してください。
パッケージのインポート
パッケージをインポートするときに、InterSystems IRIS はインポートするパッケージ内で短いクラス名を検索します。クラス定義では、クラスの Import 指示文または ObjectScript の #IMPORT 指示文を使用してパッケージをインポートできます。このセクションでは、これらの指示文について説明し、User パッケージに対する影響と、サブクラスに対する影響について述べ、いくつかのヒントも紹介します。
クラスの Import 指示文
クラス定義の最上位 (Class 行の前) に、クラスの Import 指示文を含めることができます。この指示文の構文は、以下のようになります。
Import packages
Class name {}
packages は、単一のパッケージ、または括弧で囲んだ複数のパッケージのコンマ区切りリストのいずれかにします。Import は大文字と小文字を区別しませんが、ここに示すように、通常は最初の文字を大文字にします。
クラス・コンテキストでは、現在のパッケージが常に暗黙的にインポートされます。
ObjectScript の #IMPORT 指示文
ObjectScript メソッドでは、#IMPORT 指示文でパッケージをインポートし、短いクラス名を使用して、パッケージ内のクラスを参照できます。この指示文の構文は、以下のようになります。
#import packagename
packagename はパッケージの名前です。#import は大文字と小文字が区別されません。例えば、以下のようになります。
#import Lab
// Next line will use %New method of Lab.Patient, if that exists
Set patient = ##class(Patient).%New()
#IMPORT 指示文は複数使用できます。
#import Lab
#import Accounting
// Look for "Patient" within Lab & Accounting packages.
Set pat = ##class(Patient).%New()
// Look for "Invoice" within Lab & Accounting packages.
Set inv = ##class(Invoice).%New()
#IMPORT 指示文の順序は、コンパイラが短いクラス名を解決する方法に影響しません。
明示的なパッケージのインポートによる User パッケージへのアクセスに対する影響
コードによって明示的にパッケージをインポートすると、User パッケージは自動的にインポートされません。そのパッケージが必要な場合は、パッケージも明示的にインポートする必要があります。例えば、以下のようになります。
#import MyPackage
#import User
このような論理である理由は、User パッケージをインポートしたくない場合があるからです。
パッケージのインポートおよび継承
クラスはスーパークラスから明示的にインポートされたパッケージを継承します。
クラスの名前は、現在のクラス名ではなく、その名前が最初に使用されたコンテキストで解決されます。例えば、User.MyClass で MyMethod() メソッドを定義してから、User.MyClass を継承する MyPackage.MyClass クラスを作成し、これをコンパイルするとします。この場合、InterSystems IRIS は継承した MyMethod() メソッドを MyPackage.MyClass でコンパイルしますが、このメソッドのクラス名は User.MyClass のコンテキストで解決されます (このメソッドをこのコンテキストで定義しているからです)。
パッケージのインポートのヒント
パッケージをインポートすることで、さらに柔軟性のあるコードを作成できます。例えば、以下のようなコードを作成できます。
#import Customer1
Do ##class(Application).Run()
App.MAC を以下のように変更します。
#import Customer2
Do ##class(Application).Run()
App.MAC をリコンパイルするときには、Customer2.Application クラスを使用します。このようなコードを作成するには計画が必要です。つまり、コードの互換性だけでなく、ストレージ構造への影響も考慮する必要があります。