javaによるユーザ定義関数を定義するにはFunctionImplementationインタフェースを実装したオブジェクトを 作成し、defineUserFunctionメソッドで登録します。
(defineUserFunctionメソッド)defineUserFunction(FunctionImplementation func);
FunctionImplementationインタフェースは、1個で複数の関数を定義できる インタフェースです。 以下のメソッドをサポートしている必要があります。
(FunctionImplementationインタフェース)| メソッド | 意味 |
|---|---|
| String[] names() | このクラスで定義されている関数名の配列を返す。 |
| int numberOfArgs(String name) | 指定した名前の関数の引数の個数を返す。 |
| boolean supports(String name) | 指定した名前がこのクラスで定義されている関数名であるときtrueを返す。 |
| BigDecimal value(String name, BigDecimal[] args) | 指定した名前の関数のBigDecimalの関数実行結果を返す。 |
| double value(String name, double[] args) | 指定した名前の関数のdoubleの関数実行結果を返す。 |
他のメソッド(names, numberOfArgs, value)は全てFunctionAdaptorが上記の 実装から「うまくやって」くれます。
(FunctionAdaptorクラス使用例)
//ユーザ関数実装のサンプル
class UserFuncSample extends FunctionAdaptor{
//円周の計算
double circle(double r){
return 2.0 * r * Math.PI;
}
}
//メインのクラス
class MainClass {
public static void main(String[] args) {
try{
FormulaEvaluator fe=new FormulaEvaluator();
fe.defineUserFunction(new UserFuncSample()); //ユーザ定義関数の定義
System.out.println(fe.dEvaluate("circle(2.0)"));//ユーザ定義関数の呼出
} catch (Exception e){
e.printStackTrace();
}
}
}
なお、システム定義関数もFunctionAdaptorを拡張してプログラムしていますので
ソースコードを参考にしてください。(src/com/sanpudo/formula/SystemFunctions.java)
同じクラスで同名の関数でdouble, BigDecimalの両方を必ずサポートしている必要は ありません。しかし、もし両方サポートする場合は引数の個数が 同じでなければなりません。制約に違反すると例外がスローされます。
異なるクラスで同名の関数を登録した場合は、後に登録した方が優先されます。
FunctionImplementationインタフェースを実装したオブジェクトを、 インスタンスを作成するのではなく、クラス名を指定してロードする事も 可能です。loadUserFunctionメソッドを使います。インスタンスの生成は このメソッドの中で行われます。 ロードされるクラスは引数無しのコンストラクタをサポートしている必要が あり、また、CLASSPATHの通った場所にある必要があります。
(loadUserFunctionメソッド)defineUserFunction(String クラスパスの通ったクラス名);(loadUserFunctionメソッドの例)
formulaEvaluator.defineUserFunction("com.sanpudo.UerFuncSample");
このメソッドがサポートされていると言う事は、メインのプログラムを
コンパイルしなおす必要なく、外部で準備したユーザ定義関数を
実行時に名前を指定してロードするプログラムが作れる事を意味しています。