ウィリアムのいたずらの、まちあるき、たべあるき

ウィリアムのいたずらが、街歩き、食べ物、音楽等の個人的見解を主に書くブログです(たま~にコンピューター関係も)

依存性の問題の対応策(その4:引数の共通化しても、実行時に知らせる方法)

2006-11-27 17:59:29 | Weblog

なぜか、シリーズ化してしまった、依存性の問題の対応策、前回は、汎用性を高めるため、引数だけ、共通化するという方法を書きました。
 具体的には、

1.引数をハッシュマップなどにいれ、そのハッシュマップを引数にする

  か、Strutsなどで利用されている

2.引数を「ある型」から継承したものにして、メソッドの引数には、「ある型」を書く

ということについてあげました。

今回は、1において、コンパイルでは、引数は共通だから通るんだけど、実行時には、落ちて分かるようにする方法を書きます。実は、この方法、2では、同じ仕組みでわかるようになってます。

 では、それについて書きます。



■「引数は共通」だけど、実行時に落ちる方法(変更前)
 いままでの例である、エラーメッセージを出すという話です。

 今回は、引数をまず、argというクラスの中に入れ、そのargを、ハッシュマップにセットします。
 argの内容は、以下のとおり
public class arg {
	public	String	msg 	= 	null;
}


そーなると、a(呼び出し側)は、こんなかんじ
import java.util.*;

public class a {
	/*
	 * メイン処理
	 * @param	args	外部から渡される引数
	 */
	public static void main(String[] args) {
		HashMap map =	new HashMap();
		arg hikisu	=	new arg();
		hikisu.msg	=	"aのメッセージ";
		map.put("arg",hikisu);
		b.errmsg(map);
	}
}


呼ばれて、エラーメッセージを出すbは、こんなかんじ
import java.util.*;

public class b {
	/**
	 * エラーメッセージ出力
	 * @param	map		引数が入ったハッシュマップ
	 */
	public static	void errmsg(HashMap map)
	{
		arg	hikisu	=	null;
		try
		{
			hikisu	=	(arg)map.get("arg");
			if ( hikisu == null )
			{
				System.out.println("引数がない");
				throw new RuntimeException();
			}
		}
		catch(Exception e)
		{
			System.out.println("引数が古い");
			throw new RuntimeException();
		}
		
		//	出力		
		System.out.println(hikisu.msg);
	}
}


もう一方の呼ばれる側d(呼び出し側)は、こんなかんじ
import java.util.*;

public class d {
	/*
	 * コンストラクタ
	 */
	public	d()
	{
		HashMap map =	new HashMap();
		arg hikisu	=	new arg();
		hikisu.msg	=	"作成";
		map.put("arg",hikisu);
		b.errmsg(map);
	}
}




■「引数は共通」だけど、実行時に落ちる方法(仕様変更の結果)
ここで、レベルを入れるということに変更します。
ただし、aとbだけに連絡が行っているとします。

 今度新しい引数をarg1とすると、その内容は、以下のとおり
public class arg1 {
	public	String	msg 	= 	null;
	public	int	level	=	0; 
}


このとき、aは、以下のとおり
import java.util.*;

public class a {
	/*
	 * メイン処理
	 * @param	args	外部から渡される引数
	 */
	public static void main(String[] args) {
		HashMap map =	new HashMap();
		arg1 hikisu	=	new arg1();
		hikisu.msg	=	"aのメッセージ";
		hikisu.level = 	10;
		map.put("arg",hikisu);
		b.errmsg(map);
	}
}

(赤字は仕様変更で修正したところ)

そして、bは、以下のとおり
import java.util.*;

public class b {

	/**
	 * エラーレベル
	 */
	public static	int	errlevel	=	0;	

	/**
	 * エラーメッセージ出力
	 * @param	map		引数が入ったハッシュマップ
	 */
	public static	void errmsg(HashMap map)
	{
		arg1	hikisu	=	null;
		try
		{
			hikisu	=	(arg1)map.get("arg");
			if ( hikisu == null )
			{
				System.out.println("引数がない");
				throw new RuntimeException();
			}
		}
		catch(Exception e)
		{
			System.out.println("引数が古い");
			throw new RuntimeException();
		}
		
		//	出力
		if ( hikisu.level >= errlevel)
		{		
			System.out.println(hikisu.msg);
		}
	}
}

(赤字は仕様変更で修正したところ。> は、実際には半角)
 つまり、引数を受け取るときにキャストし、古い型だったら、ランタイム例外で落とします。

で、dは修正していませんが、問題なくリンクできます。
そして、dがどこからか呼ばれて、表示しようとすると、
”引数が古い”とでて、ランタイムエラーになるのでわかります。




 これは、引数をキャストするとき、型が違うため、エラーになるということを利用しています。
 おなじような現象として、Strutsなどで、実際に引数を利用するときは、引数をキャストして使うので、ここで、古い型のものでかいてあれば、エラーになります。

 ということで、
・今回の例のように、なにかを包んで、中身から出すときにキャストして、
 古かったらエラーにするもの(ある意味委譲のやり方に似ている)や、


・Strutsのような、継承の型で、親の型を引数とし、実際に利用するときキャストして
 古かったらエラーにするものがあるのですが、

この継承でやる方法と、委譲でやる方法、意味があって、使い分けます。
それについては、次回のこのシリーズに書きます。
この記事についてブログを書く
  • Twitterでシェアする
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする
« Javaの画面表示-その21:... | トップ | ライブドア、最終損益が40... »
最新の画像もっと見る

Weblog」カテゴリの最新記事