前回のが、
肝心な部分はUnicodeエスケープを利用して実は全部コメントになっているというインチキ甚だしかったので、
真面目に取り組んでみました。
package ひだまりスケッチ;
public class x365 {
static class 来週も見てくださいね extends X {}
static 来週も見てくださいね X = new 来週も見てくださいね();
static class X {
public <T> boolean 宿題だよ(T t) {
System.out.println(t.getClass().getCanonicalName());
return true;
}
}
// ----- main method -----
public static void main(String[] args) {
boolean _ = true;
_ = X instanceof
X|_|X .< 来週も見てくださいね
>宿題だよ(X);
}
}
コンセプト
Javaの場合、演算子オーバーロードができないので、アスキーアート(以下AA)部分をどう処理するかというのが
大きな問題となります。「X / _ / X」の部分と吹き出しの「<」ですね。
今回はちょっとAAをいじってて「X | _ | X」になっており、
目の部分が"/"(除算)の代わりに"|"(論理演算のOR)になっています。
今回は、セリフの吹き出しのための "<"を不等号ではなく、
ジェネリックなメソッドの型パラメータ指定のための<>として使っています。
セリフの中身「来週も見てくださいね」が文字列ではなくてクラス名になっているんですね。
ここで厄介なのはふたつのXです。AAの左側と右側でXが出てきますが、
右側のXは続くメソッド呼び出しのためにオブジェクトの参照である必要があります。
しかし、左側はOR演算子が隣接するのでbooleanかint型である必要があります。
そこで、Xという型名のクラスを用意して、「クラス名としてのX」と「変数としてのX」と
ふたつのXを使い分けています。型名をOR演算子に隣接させるためにinstanceof演算子を利用しました。
メッセージはクラスXの「宿題だよ」メソッドで出力していますが、
Class#getCanonicalName()を使ってクラスの正規名を出力しています。
こうすることで、パッケージ名+親クラス名+クラス名となって出力されるわけです。
間にピリオドが入っちゃうのは御愛嬌と言うことで。
コンセプト比較
矢野さんの手法は、
assertキーワードを使って"<"によって作られたbooleanを利用して
assert警告のメッセージに吹き出しの文字列を利用することで演算子を処理しています。
Thread#setDefaultUncaughtExceptionHandler()でassertを拾ってメッセージ表示というのが
キモいところです(褒め言葉)。
Derive Your Dreamsさんの手法は
AA部分はintによる演算にしているのですが、Xや_の変数を内部クラスのフィールドにし、
static importを利用してクラスを次々とロードし、satatic フィールドの初期化を起こさせ、
その初期化処理でメッセージを出力するという機構。
ふたつのX問題は片方をstatic import、
片方を親クラス+子クラスの形で呼び出すことで解決しています。
注意
このコードはパッケージ名を解決してやらないと動かせません。
"ひだまりスケッチ"packageなので、ソースフォルダの下に"ひだまりスケッチ"という
フォルダを作ってx365.javaを作成する必要があります。出力結果は
ひだまりスケッチ.x365.来週も見てくださいね
となります。
投稿日時 : 2008年7月11日 22:14