ユーザ定義関数(java)

ユーザ定義関数(java)のメリット

javaでユーザ定義関数を記述して登録できるのは算譜堂数式エバリュエータの強力な特長です。 これは基本的にプログラムで出来る事であれば何でもユーザ定義関数として実装できる事を 意味しています。例えば、 等は通常の式では記述できませんが、javaでプログラムを組めばどんな機能でも 一見普通の関数として呼び出せます。例えば、「現在のドル・円レートを返す関数」 等も(そういうデータソースが整備されている環境であれば)実装可能です。

ユーザ定義関数(java)の定義

javaによるユーザ定義関数を定義するにはFunctionImplementationインタフェースを実装したオブジェクトを 作成し、defineUserFunctionメソッドで登録します。

(defineUserFunctionメソッド)

 defineUserFunction(FunctionImplementation func);

FunctionImplementationインタフェース

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の関数実行結果を返す。

FunctionAdaptorクラス

FunctionImplementationインタフェースはユーザが自分で実装してももちろん問題ありませんが、 実装のためにはFunctionAdaptorクラスを拡張することをお勧めします。FunctionAdaptorクラスは FunctionImplementationインタフェースを実装しており、ユーザは定義したい関数の 本当の計算部分だけを記述するだけで、必要なメソッドは自動的に対応します。 ユーザの記述は だけです。

他のメソッド(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の実装時に、値を評価する関数の中で 評価できない状況が発生したときは、FunctionEvalExceptionをスローしてください。

クラス名によるユーザ定義関数の登録

FunctionImplementationインタフェースを実装したオブジェクトを、 インスタンスを作成するのではなく、クラス名を指定してロードする事も 可能です。loadUserFunctionメソッドを使います。インスタンスの生成は このメソッドの中で行われます。 ロードされるクラスは引数無しのコンストラクタをサポートしている必要が あり、また、CLASSPATHの通った場所にある必要があります。

(loadUserFunctionメソッド)

 defineUserFunction(String クラスパスの通ったクラス名);

(loadUserFunctionメソッドの例)

 formulaEvaluator.defineUserFunction("com.sanpudo.UerFuncSample");

このメソッドがサポートされていると言う事は、メインのプログラムを コンパイルしなおす必要なく、外部で準備したユーザ定義関数を 実行時に名前を指定してロードするプログラムが作れる事を意味しています。