- PR -

メソッドの入れ替え

投稿者投稿内容
progman
大ベテラン
会議室デビュー日: 2005/06/08
投稿数: 227
投稿日時: 2007-08-10 09:50
以下のコードがあって、Test1の修正や他にクラスを追加してもいいのですが
Bean1,UBeanは変更したくありません。
ですがBean1のメソッドgetStr1の処理内容を変更したいのですが、なにかよい方法は
あるでしょうか?

Bean1と類似したクラスが多くあって、すべて同じ名前で、処理内容もほぼ同じ
メソッドをもっています。
また、Test1側からの呼び出しは全てrunメソッドであり、その先でgetStr1を呼んで
います。

このメソッドgetStr1からの返却を一次的に変更して利用したいのです。
現在の返却値 abcde:ABCDE
変更後の返却値 aBcDe:ABCDE
としたいのです。

コード:
public class Test1 {

public static void main(String[] args ) {
UBean bean = new Bean1();
String ret = bean.run("aBcDe");
System.out.print(ret);
}
}

public class Bean1 extends UBean {
public String run( String m ) {
return other( m ) + ":" + getStr1( m );
}

public String other( String m ) {
return m.toLowerCase();
}
public String getStr1( String m ) {
return m.toUpperCase(); // ここを return m; としたい。
}
}

public class UBean {
public String run( String m ) {
return m;
}
}




Proxyというクラスがあって、これを使えばいいかなとおもったのですが、
getStr1はinterface定義されたメソッドではないので使えません。
そこで
public interface Conditionable {
public String run( String m );
public String getStr1( String m );
}
 public class DBean1 extends Bean1 implements Conditionable{}
とダミーをかまして、DBean1をTest1から使うようにしましたが問題があります。

1 Test1から直接呼び出していないメソッド(getStr1)は入れ替えできないようです。
2 クラス毎にダミー定義が必要となるので好ましくありません。
  ※Test1に相当する処理は文字列としてBean1の名前を受け取ってreflectを使用して
   runメソッドを呼んでいるので、Bean1に相当するクラス名に依存する記述はした
   くありません。

2は回避策はあるのですが、1はどうしようもありません。
Proxyでも、それ以外でもなにかよい方法はないでしょうか?
JDK1.5がターゲットです。


*コードのタグ誤り変更しました。

[ メッセージ編集済み 編集者: progman 編集日時 2007-08-10 10:00 ]
nagise
ぬし
会議室デビュー日: 2006/05/19
投稿数: 1141
投稿日時: 2007-08-10 09:56
引用:

progmanさんの書き込み (2007-08-10 09:50) より:
 public class DBean1 extends Bean1 implements Conditionable{}
とダミーをかまして、DBean1をTest1から使うようにしましたが問題があります。

1 Test1から直接呼び出していないメソッド(getStr1)は入れ替えできないようです。
2 クラス毎にダミー定義が必要となるので好ましくありません。
  ※Test1に相当する処理は文字列としてBean1の名前を受け取ってreflectを使用して
   runメソッドを呼んでいるので、Bean1に相当するクラス名に依存する記述はした
   くありません。



意味がよく分からないのですが、getStr1メソッドをオーバーライドしたにも関わらず
getStr1の元の実装が呼び出されていると言っています?
progman
大ベテラン
会議室デビュー日: 2005/06/08
投稿数: 227
投稿日時: 2007-08-10 10:09
nagiseさんレスありがとうございます。
オーバーライドして駄目なのではないです。
任意のクラスのメソッドgetStr1の内容を動的に変更したいのです。

こういう方法でもいいです。
Bean1に相当するクラスを継承するDBeanというクラスがあってgetStr1がオーバーライド
されている。
それで、継承元のクラスを動的に変更できる。
※Bean1に相当するクラスは全てメソッド run,getStr1をもっています。
Anthyhime
ぬし
会議室デビュー日: 2002/09/10
投稿数: 437
投稿日時: 2007-08-10 10:15
AspectJでできそうな気がします。
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2007-08-10 10:55
java.lang.instrument.Instrumentation+ASM/Javassist/BCEL...
辺りの組み合わせでできそうな気がしますが、
ビジネスロジックのためにバイトコード操作は、
かえって保守性が悪くなると思います。
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2007-08-10 10:59
もう一つ思いついたのが、classファイルそのものの書き換えですね。
ビルド時に別管理しているソースのclassファイルと差し替えるという方法です。
nagise
ぬし
会議室デビュー日: 2006/05/19
投稿数: 1141
投稿日時: 2007-08-10 11:00
引用:

progmanさんの書き込み (2007-08-10 10:09) より:
nagiseさんレスありがとうございます。
オーバーライドして駄目なのではないです。
任意のクラスのメソッドgetStr1の内容を動的に変更したいのです。



任意のクラスってのは複数のクラスを指しているんですね?
クラスA、クラスB、クラスC...とあって、
そのメソッドを実行時に変えたい、と。

該当のメソッドがinterfaceにくくりだしてあるなら多少マシでしょうが、
基本的にはイロモノでの対処しかできない気がしますね。
いわゆるバッドノウハウの部類でしょう。
だっちょ
大ベテラン
会議室デビュー日: 2006/12/05
投稿数: 115
投稿日時: 2007-08-10 12:43
イロモノというのであれば、JDIで復帰するときにTrapして変更する手があります。
もっと簡単にjdbで起動してbreakしたところでコマンドを実行する(デバッグ操作そのもの)をbatchみたいに実行するようにして、実行する手もあったはずですが、単純に
batchやプロセス実行ではコマンド入力できないようです。

スキルアップ/キャリアアップ(JOB@IT)