[Java] 既存のクラスを(擬似的に)拡張したい

2018年7月17日火曜日

Java

サブクラスしか持っていないメソッド

Javaでサブクラスがスーパークラスが持っていないメソッドを持っているときに統一的に取り扱おうとすると面倒なことが多い。
本来はサブクラス側を直した方がいいのかもしれないけど、既存のクラスでこちらが修正できない場合も多々ある。

例えば、SQLExceptionはExceptionが持っているgetMessageだけではなく、getErrorCodeやgetSQLStateを持っているけど、これらを統一的にログに出力したかったりする。

https://docs.oracle.com/javase/jp/8/docs/api/java/sql/SQLException.html

型が事前にわかっている場合

C#の拡張メソッドみたいにstaticメソッドを作って、第一引数に注目しているオブジェクトを渡す。

B extends Aの関係で、AクラスがgetMessage,BクラスがgetMessageとgetCodeを持っている場合で、型が事前にわかっている場合は単純にオーバーロードで対処できる。
static String getMessage(A self) {
    return self.getMessage();
}

static String getMessage(B self) {
    return self.getCode + ":" + self.getMessage();
}

ただし、これは実行時ではなく、コンパイル時にオブジェクトの型がAかBかわかっている場合に限られる。

型が事前にわかっていない場合

実行時の型が分からない場合はinstanceofで判定したのちにキャストして、オーバーロードメソッドを呼ぶしかない。
static String getMessage(A self) {
    if (self instanceof B) return getMessage((B)self);
    return self.getMessage();
}

static String getMessage(B self) {
    return self.getCode + ":" + self.getMessage();
}

オーバーロードメソッドで分けておけば、ソースコードの見通しがよくなるかなといった程度で、別になにかが解決されたわけもないって感じ。
なにか、もっといい方法がないかな...