InterSystemsCachéObjectScript(COS)言語は毎年開発されており、新しいコマンドと機能が追加されています。 残念ながら、現時点では、COSのルーチンは最初のクラスのオブジェクトではありません。つまり、ルーチン(関数、メソッド)をパラメーターとしてルーチンに渡したり、ルーチンから返すことはできません。
ただし、これらの制限を緩和する方法があります。
猫の下で、サブルーチンへの引数としてコードを渡すためのいくつかのオプションを検討してください。
次の2つの方法があるとします。
ClassMethod AllPersonsWithA()
{
rs = ##クラス ( %ResultSet )を設定します。 %新規 ()
rsを行い ます。 準備 ( 「substr(name、1,1)= 'A'のSample.PersonからIDを選択」 )
rsを行い ます。 実行 ()
rs 。 次 () {
set p = ## class ( Sample.Person )。 %OpenId ( rs。Get ( "ID" ))
pを 設定し ます。 オフィス = 「モスクワ」
pを 書き ます。 名前 、 「」 、 p 。 SSN!
Pを 殺す
}
RSSを 殺す
}
ClassMethod AllCompaniesWithO()
{
rs = ##クラス ( %ResultSet )を設定します。 %新規 ()
rsを行い ます。 準備 ( 「substr(name、1,1)= 'O'のSample.CompanyからIDを選択」 )
rsを行い ます。 実行 ()
rs 。 次 () {
set p = ## class ( Sample.Company )。 %OpenId ( rs。Get ( "ID" ))
pを 設定し ます。 名前 = "OOO" _ p お名前
pを 書き ます。 名前、!
Pを 殺す
}
RSSを 殺す
}
動的SQL-%SQL.Statementの新しいバージョンに切り替えるには、2つの場所でコードを変更する必要があります。 us%でResultSetが10箇所で使用された場合、10箇所で変更されます。
これら2つのメソッドを次のように書き換えます。
Sample.Personの特定のインスタンスを処理するメソッドを追加します。
ClassMethod ProcessPerson( p As Sample.Person )
{
pを 設定し ます。 オフィス = 「モスクワ」
pを 書き ます。 名前 、 「」 、 p 。 SSN!
}
ここでは、AllPersonsWithAメソッドをこのようなコマンドに置き換えます。
do .. OpenAndProcess ( 「substr(name、1,1)= 'A'の Sample.Person からIDを選択」 、 「Sample.Person」 、 「ProcessPerson」 )
ここで、最初の引数はクエリ、2番目はインスタンスが処理されるクラスの名前、3番目はクエリ結果の各行に対して呼び出す必要があるクラスメソッドの名前です。
企業の場合、処理方法は次のようになります。
ClassMethod ProcessCompany( c As Sample.Company )
{
cを 設定し ます 。 名前 = "OOO" _ c 。 お名前
cを 書き ます 。 名前、!
}
次のコマンドを呼び出します。
do .. OpenAndProcess ( 「substr(name、1,1)= 'O'のSample.CompanyからIDを選択」 、 「Sample.Company」 、 「ProcessCompany」 )
さて、実際には、OpenAndProcessメソッド自体:
ClassMethod OpenAndProcess( query As%String 、 className As%String 、 コールバック As%String )
{
rs = ##クラス ( %ResultSet )を設定します。 %新規 ()
rsを行い ます。 準備 ( クエリ )
rsを行い ます。 実行 ()
rs 。 次 () {
set p = $ classmethod ( className 、 "%OpenId" 、 rs。Get ( "ID" ))
do $ classmethod ( $ classname ()、 callback 、 p ) ;
Pを 殺す
}
RSSを 殺す
}
関数$ classmethod(クラス、メソッド、arg1、arg2、...)は、classクラスからmethodという名前のクラスメソッドを呼び出し、引数arg1、arg2などを渡します。
現在、%ResultSetの操作は別のメソッドに移動されており、そこで行われていることは誰にも関係ありません。
明らかに、現在のメソッドからではなく、任意のクラスからメソッドを呼び出し、コールバックに任意の数のパラメーターを渡すように、OpenAndProcessメソッドを修正できます。
コールバックのコードが非常に小さい場合は、匿名関数の一種である$ xecute関数を使用できます。 この場合のOpenAndProcessメソッドは次のようになります。
ClassMethod OpenAndProcess( query As%String 、 className As%String 、 コールバック As%String )
{
rs = ##クラス ( %ResultSet )を設定します。 %新規 ()
rsを行い ます。 準備 ( クエリ )
rsを行い ます。 実行 ()
rs 。 次 () {
set p = $ classmethod ( className 、 "%OpenId" 、 rs。Get ( "ID" ))
set res = $ xecute ( コールバック 、 p )
Pを 殺す
}
RSSを 殺す
}
また、処理はクラスメソッドではなく、文字列で囲まれます。
set query = "substr(name、1,1)= 'A'のSample.PersonからIDを選択"
do .. OpenAndProcess ( query 、 " Sample.Person " 、 "(p)s p.Office =" "Moscow" "w p.Name、" "" "、p.SSN、!q 0" )
入力パラメーターは、行頭の括弧内に示されています。 他のすべての変数は、現在のコンテキストで検索されます。 次の例では、inは仮パラメーターであり、bの値は現在のコンテキストから取得されます。
USER> s a = "(in)ret in + b"
USER> s b = 10 w $ xecute ( a 、2)
12
USER> s b = 13 w $ xecute ( a 、2)
15
$ xecuteを使用してコードを渡すことの欠点は、同じ行に複数のコマンドを配置できないことです。 さらに、構文チェックはコード実行中にのみ実行されます。 一方、一度だけ使用されるメソッドを作成する必要はありません。
ドキュメント: