ねこび〜ん

http://ja.netbeans.org/nekobean/
http://blogs.sun.com/katakai/entry/nekobean_on_netbeans_newsletter

この間の東北デベロッパーズコミュニティの飲み会でNetBeansのキャラクターが出来たらしい。
今、NetBeansIDEを開くと、ブログの内容がねこび〜ん祭りになってて面白いです。
で、おもわず、NetBeansのアイコンとスプラッシュ画面を書き換えてみてしまいました。
何をやってるんだろう。。。と思いつつ。

スプラッシュ画面

アイコン

製品についての画面

  • exeアイコンの書き換え方。

http://sakurai.s59.xrea.com/java/nekobean.ico

アイコンエディットするツールでアイコンつくります。
今回は、「@icon変換」http://www.towofu.net/soft/ を使いました。
そして、次に作ったアイコンを「IconChanger」 http://www.vector.co.jp/soft/win95/amuse/se372418.html
で、C:\program files\NetBeans\bin\netbeans.exe を書き換えればOKです。

  • ウィンドウのアイコンの書き換え方。

C:\Program Files\NetBeans 6.0.1\nb6.0\core\locale\core_nb.jar
内のframe_nb.gifを書き換えます。

  • スプラッシュ画面の書き換え方。

C:\Program Files\NetBeans 6.0.1\nb6.0\core\locale\core_nb.jar
内のsplash_nb.gifを書き換えます。splash_nb.gifは拡張子がgifになっていますが、
pngで保存するとフルカラーが使えます。
その他、about_nb.pngを書き換えると、製品についての画面も変更できるようです。

リフレクションを使ったインタプリタ

中置演算子ってオブジェクト指向ととても親和性が高いよなぁと思う、今日この頃みなさんいかがお過ごしでしょうか?
Javaには名前でクラスやフィールド、メソッドなどを取得したり実行したりできるリフレクションなるAPIがあります。
そのリフレクションを使って以下のようなインタプリタの仕組みを作ってみました。


軽く説明します。

まず、オブジェクトを表すための大元となるCObjというクラスを定義します。
CObjを継承して数字を表すCInt、文字列を表すCStrを作ります。
そして、構文木を表すCMsgを作ります。
例えば1+2の構文木はCMsg内に[1,add,2]を持ちます。(+はメソッド名に使えない都合上addにしています。)
各々のクラスはtoStringで文字列に変換します。
各々のクラスにインタプリタで実行するメソッドを書いておきます。
例えば足し算をするにはCInt.addメソッドを追加しておきます。
そして、execメソッドで各オブジェクトが実行します。
CInt.execやCStr.execはそのまま値を返します。そして、CMsgが中置演算子の演算を実行します。
CMsgが持っている足すという情報は関数としてもつことは出来ませんので、文字列として持ちます。
この文字列から直接、CIntのaddメソッドを呼ぶことはできないので、ここでリフレクションを使います。
これで、switch文を使わずにインタプリタを作ることができます。


こういったテクニックを使うと、分かりやすくプログラミング言語が作れるかもしれません。
今悩んでるのが、特殊形式たとえば、代入などをどう処理するかというところです。
ifはなんとかなりそうですが、代入がウームです。

import java.lang.reflect.Method;

public class CObj {
	public String toString() { return str(null).toString();}
	public CStr str(CObj o) { return new CStr("[Obj]"); }
	public CObj exec()  throws Exception { return this; }
	public static CStr Str(String s) { return new CStr(s); }
	public static CInt Int(int s) { return new CInt(s); }
	public static CMsg Msg(CObj obj, String s, CObj prm) { return new CMsg(obj,s,prm); }
}

class CInt extends CObj {
	public int data;
	public CInt(int data) { this.data = data; }
	public CInt add(CInt p) { return new CInt(data + p.data); }
	public CInt add(CMsg p) throws Exception { return new CInt(data + ((CInt)p.exec()).data); }
	public CInt mul(CMsg p) throws Exception { return new CInt(data * ((CInt)p.exec()).data); }
	public CInt mul(CInt p) { return new CInt(data * p.data); }
	public CStr str(CObj o) { return new CStr(""+data); }
}

class CStr extends CObj {
	public String data;
	public CStr(String data) { this.data = data; }
	public CStr add(CObj p) throws Exception { return new CStr(data + p.exec().toString()); }
	public CStr str(CObj o) { return this; }
	public String toString() { return data;}
}

class CMsg extends CObj {
	public CObj obj;
	public String op;
	public CObj prm;
	public CMsg(CObj obj, String op, CObj prm) {
		this.obj = obj;
		this.op  = op;
		this.prm = prm;
	}
	public CStr str(CObj o) { return new CStr("["+obj+","+op+","+prm+"]"); }
	public CObj exec() throws Exception {
		Method method = null;
		for(Class cls = obj.getClass(), pcls = prm.getClass();;) {
			try {
				method = cls.getMethod(op, new Class[] {pcls});
				break;
			} catch (NoSuchMethodException e) {
				try {
					pcls = pcls.getSuperclass();
				} catch (Exception e2) {
					throw e;
				}
			}
		}
		return (CObj)(method.invoke(obj,new Object[] {prm}));
	}
}

class CTest extends CObj {
	public static void main(String[] argv) throws Exception {
		System.out.println(Msg(Str("1+2="), "add", Msg(Int(1), "add", Int(2))));
		System.out.println(Msg(Str("1+2="), "add", Msg(Int(1), "add", Int(2))).exec());
		System.out.println(Msg(Str("1+2*3="), "add", Msg(Int(1), "add", Msg(Int(2), "mul", Int(3)))).exec());
	}
}