本Blog(3代目)について

☆RSSについて
RSSは今まで通りと変わらないようにしてあります。
現在最新のRSSのURLは
http://hdmr.org/d/rss 
です。

☆コメントについて
コメントについては2011年4月よりDISQUSを利用しています。
誰でもコメントできますが、DISQUS・Google・Twitter・FacebookのIDやその他のOpenIDでのログインが必要です。
詳細な使い方については DISQUSのコメント機能の使い方 をご覧ください。
DISQUSではコメント以外に「いいね!」など残すことが出来ます。ぜひご利用ください。

☆リンクについて
自由にリンクを貼っていいです。各記事へのリンクもかまいません。
承認は取る必要もないです。

☆トラックバックについて

2021年3月をもって停止しました。

新入生もまたBlogerであった

ちょっと作業してます。このWebサイトにとって有益な作業です。
そんなわけでLibserverをいじってたのですが、Vine Linuxって4.2になってたんですね。
そんなわけでyumでアップデート。
便利でよろしいな。
さて、最近部に新入生が入ってきて、それはなんてことないことなのですが、
最近ミーティングがあって、Live Messengerの話が出てきました。
Windows Live Messengerは部の公式IMらしいです。
僕はYahoo! Messengerの方が好きなんだけど、まぁ部がそういうのだから仕方ない。
というわけでHotmail使わずにLive Passport取ってやってます。
で、彼らのメールアドレスを持って帰ってきて、招待を送りました。
礼儀正しく言えば向こうもわかってくれるので許可が返ってきました。
本名と表示名が違う混乱を避けるために、ちゃんと表示名も聞いてきたので理解しやすい。
といってもまだ名前と顔が一致しないんだけどね…
さて、Live Messngerには表示メッセージというのがあります。
ここに「レポート書いてるよ」とかいろいろ書けて便利です。
音楽情報垂れ流しにするとここに表示されます。
で、そこにいろいろ書いてくれると、ああこんなことやってるのかとよくわかるものです。
さて、それに関係してですが、HNをgoogle検索してみました。すると何人かはヒットしました。
Blogやってるんですね。ちょっとSkinが見にくい人とかいましたけど、
しかしいろんなことやってますねぇ…
ちょっとはその人のことを知れた気がする。けどまだ顔と名前が一致しない…
その中にはアニメの話書いてるなぁと思ったら急にレジストリが出てきたり、
なんかそんなまぜこぜの人もいた。このページもそうですよね。
僕がこんなことしてるってことは逆もあり得ると言うことだ。
そう、昨日までこのページを知らんかった人が急に見に来ると。
それはそれでいいことだ。ぜひRSS購読して更新を確認しましょう。

残念ながらこれはZ80ではありません

部にどういうわけか知らんけど、TK-85というワンボードマイコンがあった。
WikipediaによるとNECがかつてマイコン学習用に開発したものらしい。
で、TK-85はIntel 8085互換のCPUが載せてあるらしい。
ただ、8085はかの有名なIntel 8080に2命令追加されて、実行速度が速くなっただけ。
なので8080を扱ってる気分で扱えばいいでしょう。
というのは後からわかったことなのだが、ボードを掘り出してきたときはZ80互換のCPUが載ってるものだと思ってた。
Z80は8080よりさらに有名ですよね。8080の互換CPUなんだけど、すごい拡張された便利なCPU。
我々も実験で触れることになりました。だから掘り出してきたんだけど。
それで電源を入れて、操作方法がちんぷんかんぷんなのでちょっと調べて、
で、実験で使ったプログラムを打ち込むと予想通り動いた。
それで何も気にしてなかったんだが、他のプログラムを打つと動かん。
そのプログラムちょっと複雑なもので、IXレジスタが登場したりとZ80の拡張命令をフルに活用してる。
それから調べて8085の互換CPUだとわかったということ。なので8080でも動くプログラムを作って動かすのがよさそうです。
それなら8080のニーモニックを学習してそれで書いてアセンブリしろと言われそうだが。
我々はZ80のニーモニックに慣れてきたところなので、Z80の命令の8080から拡張された分を使わないことで手を打ってみようと思う。
そんなわけで使えない命令を隠して、使える命令の説明とフラグの変化をOOo Calcで書いて印刷した。
8080の命令は全部1バイトなので結構スマート。命令の数も思ってるより少ない。
これをみながらプログラムを書けばよさそう。
この範囲で書いてひたすらハンドアセンブリ、それで1バイトづつ打ち込んで動作させると。
手間ばっかりかかる。だけどなかなかおもしろいな。
実験で使ったZ80のボードは液晶ディスプレイまでついてるしリッチすぎる。
しかし、TK-85は結構シンプルで25のキーと7セグメントLEDが4つあるだけ、入力はともかく表示はかなり貧弱。
けど慣れるとなかなかおもしろいね。
さて、まぁそんなわけで家に帰ってきて、30分ぐらい考えて、エミュレーターでも確認してみて、
書いた8100h〜812Fhの間をバブルソートするプログラム。

        ORG 8000h
LD HL,8100h
START: LD D,H
LD E,L
LD B,(HL)
LOOP: INC HL
LD A,(HL)
CP B
JP NC,NEXT
LD (HL),B
LD B,A
NEXT: LD A,2Fh
CP L
JP NZ,LOOP
LD H,D
LD L,E
LD (HL),B
INC HL
CP L
JP NZ,START
HALT

HLをDEにコピーするのはHをD、LをEにするのを組み合わせてすれば正解だと思う。
これをエミュレータでアセンブルしたやつとハンドアセンブルしたやつを比較したら微妙に間違ってた。
やはりコンピュータはこういう仕事はよくやってくれる。
エミュレーターは時間が10秒ぐらいかかったけど、実機が本気でやったらどれぐらいかかるんだろう。

誰でも便利に電車を使えるようにするのはいいことだね

いつも電車に乗るとき、帰りは一番後ろの車両に乗ることが多い。
歩く距離が短いからなんだけどね。
で、車掌がよく見えるのだが、その横に指導員みたいなことを書いた腕章を付けてる人がいた。
どうも訓練みたいだな。結構頻繁にメモを確認してたし。
慣れるまではなかなか難しいだろうからね。きちんとやっておられたよ。
さて、乗り込んですぐ気付いたのだが、車いすの人がいた。
車掌に一番近いところに車いすの人は乗せられますね。
運転席付近に車いすスペースのある車両と、連結部付近に車いすスペースのある車両あるけど、
そんなの関係なしに、駅員は車掌の近くに乗せる。
連結部付近にあるやつは資源を有効に利用できてなくて残念だ。
そういえば乗り降りのとき駅員は板を持ってきますね。板なしでは段差がきついんだろうな。
あれはもしかして全部の駅にあるのかな。
どうしても車いすはスペース食うけど仕方ない。と思って奥の方に進もうと思ったら白杖を持った人がいた。
そういえば、よく駅で白杖を持った人を見るのだが、驚くほど器用に歩いておられるな。普段歩くところはよく理解しているのだろう。
さて、その方、どうも途中の駅で降りるらしくその支度をしておられた。
まぁぶつかっちゃまずいからちょっと移動しておいた。
それで、駅に着いた。ホームに駅員がいるのはさほど珍しいことではないからなんともおもってなかったのだが、
その駅員はどうもその人を誘導しに来たみたいだ。なるほどね−。
最近、近所の駅にエレベーターを取り付ける工事をするらしいという話を聞いた。
どうも法律で付けろということになってるらしい。
それにしてもすごい手間だし、金もかかるからねぇ…それに現状でもエスカレーターはあるし。
車いす対応じゃないけどね。
ただ、実際見てるとエレベーター以外はすごい手間みたいだな。
階段は言うまでもない。手動で車いすで段差を下る機械があるらしいんだが、すごい乗り心地が悪いらしい。
エスカレーターは車いす対応でも、エスカレーターを封鎖して、段を整えて、ゆっくり回さないといけないからどうも時間がかかる。
スロープは現実的ならいいと思うけど、高い段差をスロープで解決するのはおかしい話だ。
エレベーターなら単に足腰が弱い人でも使えて便利だからね。
しかし、あの駅に一体どうやって取り付けるんだろ…

CPUとお話しするようにプログラムが書ければいいのに

実験でZ80の機械語をいじる実験をやってたのだがZ80のボードはとても静かで、計算してるのかよくわからない。
メモリの中の値をいじるプログラムを書いて、その通り動いてるかメモリの中をのぞき見るということをやってる。
アセンブリ言語で見せられてもなんかわかりにくいわな。とくに比較とかジャンプとかのあたり。
さすがに、

ORG 8000H
LD A,(8100H)
LD HL,8101H
SUB (HL)
LD (8102H),A
HALT

みたいなのはわかりやすい。ORGはとりあえず無視。LD A,Bはa=b;みたいなもんだし、
(HL)や(8100H)なんかは、*hlや*(0x8100)みたいにアドレスを参照してるんだろう。2つ目の書き方は変だけど。
SUB (HL)はa-=*hl;という発想でいいと思う。どうも計算の類はAの値を変えるものらしい。
ここで、SUB 01H(a-=0x01;)はいいのだが、SUB (8101H)はだめ。
それをしたいなら、8101Hを一旦HLに入れるか、(8101H)をBなどに入れないとダメ。
こんな風に書けても、ある命令とない命令があるからね。アセンブラがエラーを出してきたりもする。
実験にアセンブラは使ってないけどね。表とにらめっこしてやってた。まさにハンドアセンブル。
他にない命令というと、LD (8100H),(8101H)のような命令はない。これはひどい命令だ。
LD (8102H),Aはあるけど、LD (8102H),Bのような命令はない、けどLD (HL),Bはある。
まぁアドレス扱うときはHLに入れるのが無難そうだな。横着すんなということかもしれん。
さて、このソース、

      ORG 8000H
LD B,64H
LD HL,8600H
XSET: LD A,(HL)
JP NEXT
LOOP: CP (HL)
JP C,XSET
NEXT: INC HL
DEC B
JP NZ,LOOP
LD (8664H),A
END

スパゲッティプログラムやね。しかしアセンブリ言語だとこれが限界。
まず、Bに0x64、HLに0x8600を入れましたと、それでまずAに(HL)を入れる。
それでNEXTラベルに飛んでHLを1増加、Bを1減少させる。
INCやDECはb–;のような動作をする。どうもINC (HL)のような書き方もできるらしい。ニーズあるか知らんけど。
それで、JP NZ,LOOPというのは、最後の計算が0でない(NZ)ならばLOOPラベルに飛べ。
すなわちBの値が、DEC Bで0x64,0x63…と減らされて、0x00となるまでひたすら繰り返すと言うこと。
JP NZ,LOOP〜LOOP間を0x63回繰り返すと言うことになりそうだな。
それで、CP (HL)とあるが、これはちょっと不思議な命令。
ADD Bとか、DEC Bとか、そういう計算をすると、答えが0だったらZフラグを立てたり、桁あふれがあればCyフラグを立てたりするらしい。
ただ、CP命令は計算はするが値は変えないという、けどフラグは立てるというものらしい。
CP (HL)はAの値が変わらないDEC (HL)と思えばいいと思う。
それで、JP C,XSETで繰り上がりがないか確認して、あればXSETに飛ばされて、Aに(HL)を入れて、NEXTに飛ばされて…
というものなのだが、一体何をするものなのかというと、8600H〜8663Hの間の値を符号なし1ビット整数と考えて一番大きな値を抜き出すプログラム。
A-Bで桁あふれがあるというのは、B>Aだかららしい。だからこんなやり方をするのだと。
それはいいんだが、課題に、符号ありのときどうすればいいか考えろってのがある。
で、どうも符号ありなら、JP C,XSETをJP M,XSETにすればよさそうだと思った。
これはA-B<0ならSフラグが立って、MにすればSフラグが立ってれば飛ばされるはず。
それでうまくいくと思ったのだが、実際は桁あふれがある加減でなかなかうまくいかない。
こういうのを解決する方法があるんだろう。
それでCのコンパイラやらはそれを利用してどうやってやるか考えてるんだろう。
ありがたい話だ。すばらしい通訳だな。

すべての始まり、Objectクラス

Objectクラスには3つの仮想メソッドがあるらしい。
public virtual string ToString();
public virtual bool Equals(object obj);
public virtual int GetHashCode();
今まで何度かIFormattableを実装したことはあったが、ObjectクラスのToStringメソッドのことはすっかり忘れていた。
すべてのクラスは突き詰めればObjectクラスを継承していることになる。
継承するクラス名を書かなければObjectクラスを継承したことになる。
そんな都合でObjectクラスにあるメソッドはすべて持っているのだが、
この3つはオーバーライドしないと都合が悪い。
ToStringはオーバーライドしないと、hidemaro.myintのようにクラスの名前が返ってきてしまう。
これの要領はIFormattableのToStringと似てるけど、引数が違うからね。Objectの方は引数なし。
このObjectのToStringのオーバーライドはIFormattableを実装するために自作したToStringを利用するのが便利だろう。

public override string ToString() {
return this.ToString("d", null);
}

こんな感じ。
Equals・GetHashCodeはまず間違えなく正しくない値を返してくる。
で、まずEqualsの方は、メンバ変数をひたすら比較すればいい。

public override bool Equals(object obj) {
foo other = (foo)obj;
return this.a==other.a&&this.b==other.b;
}

という調子。まぁこれは何となくわかる話。
GetHashCodeはよくわからんのだが、どうも同じ意味を持つインスタンス同士は同じ値を返すべきらしい。
で、紹介されてる方法を参考に書くとこうするといいらしい。

public override int GetHashCode() {
return this.a.GetHashCode() ^ this.b.GetHashCode() ;
}

XORでメンバ変数のそれをひたすらくっつければいい。
なので自作クラスがあるならそれにも同様にGetHashCode()をオーバーライドしておきましょうと。
さて、そんな具合でやってました。
しかしVisual Studioは素晴らしいね。
overrideと打ってスペースを1つ入れると、オーバーライドできるメソッドのリストが出てくる。
楽ですねぇ。まぁわからなければオブジェクトブラウザで探せばいいだけだけど。

値渡しとクラスのインスタンスの罠

最近C#の話ばっかりだが、部のページでOOP特集を書いてるものでいろいろ調べてたんだ。
さて、そういえばC#の引数は値渡しという話があったがよくわからないのでいろいろ試してみた。
まずこんなクラスを作ってみた。

class myint : IFormattable {
private int v;
public myint(int v0) { v=v0; }
public void incl() { v++; }
public string ToString(string format, IFormatProvider formatProvider) { return v.ToString(format, formatProvider); }
}

中にintを1つ格納しただけのクラスだな。クラスというところは重要、構造体ではない。
だいたい動作は予想できると思うけどね。
その上でこんなものを動かしてみた

int i=10;
myint mi=new myint(i);
Console.WriteLine("{0}", i);
mi.incl();
Console.WriteLine("{0}", i);
Console.ReadKey(false);

さて、これを動かすと両方10が返ってきた。
手順としてはまずmyintのインスタンスを作成するが、このときiの中に入った10という値を変数vに代入した。
なのでこのとき変数vは10を示している。当然ここの値を1増やしたところでiには影響がない。
値渡しというのは仮変数(であってるのか)のv0は、引数に書いた変数、今回はi、を丸ごとコピーするということ。
だから、仮変数のv0と引数に書いた変数iは無関係になっていることはわかるとおもう。
さらに構造体(値型)の代入は中身を丸ごとコピーすることで行うので、コンストラクタでvに代入した時点で仮変数のv0とは無関係。
そのv0をinclメソッドでいじろうがこれも無関係。
だからinclメソッドを動かす前後でiの値は変わってない。これが構造体の特徴ですね。
さて、では中に入れる変数をクラスのインスタンスにしてみよう。

class mymyint : IFormattable {
private myint v;
public mymyint(myint v0) { v=v0; }
public void incl() { v.incl(); }
public string ToString(string format, IFormatProvider formatProvider) { return v.ToString(format, formatProvider); }
}

さっきとだいたい同じものだな。違うのはmyintを納めたものであるということ、
それにともなってinclメソッドがそこからさらにmyintのインスタンスのinclメソッドを呼び出している。
これでもってこんなものを動かしてみる。

myint mi=new myint(10);
mymyint mmi=new mymyint(mi);
Console.WriteLine("{0}", mi);
mmi.incl();
Console.WriteLine("{0}", mi);
Console.ReadKey(false);

まぁさっきとあまりかわらない。結果は前が10、後が11。
なぜこうなるのかという話だが、クラスのインスタンスの変数はCで言うところのポインタだ。
なので、miには1行目で、たとえば「甲地を見よ」と書いたものを代入されたようなものだ。
その上でmmiのコンストラクタに引数として渡した。値渡しなのでコピーされると言った。
しかしコピーされたのは、「甲地を見よ」ということだけ。
だからもしこのコンストラクタの中でその仮変数v0の中身にコンストラクタで全く新しいインスタンスを代入して、
たとえばv0が「乙地を見よ」に変わったとしても、値渡しだから、引数に書いたmiには反映されない。
けど今回はそんなことせず、そのv0をただvに代入しています。
こうなると、miとvはそれぞれ同じ場所を示していることがわかりますよね。
その上で、vのinclメソッドを動かします。すると、vの内容だけ変わります。vの値は変わりません!
その上、vもmiも指していることは同じ。だからmiの値は変わってないのに内容はさっきの動作で変わってしまっている。
その結果、miの内容を表示させたら、1増えた11になってたわけです。なるほど。
もしvの内容とmiの内容を無関係にしたければ、改めてvの内容を作って、miと同じ内容をコピーしないといけない。
このためにコピーコンストラクタというのが欲しくなるわけか。
さて、この特徴を知ったら、foreachで内容が変えられるような気がしてきました。
そこでこんなクラスを自作しました。完璧じゃないけどある程度は動く。

class changeable<T> {
private T _v;
public changeable(T v0) { _v=v0; }
public changeable(changeable<T> v0) { _v=v0._v; }
public void change(T v0) { _v=v0; }
public static implicit operator changeable<T>(T v0) { return new changeable<T>(v0); }
public static implicit operator T(changeable<T> v0) { return v0._v; }
}

Nulltable構造体を参考に作ってみました。まぁこれはクラスですが。
このクラスのインスタンスのchangeメソッドで中身を書き換えることができる。
というものなのだが、これがどう有用かは見て欲しい。

changeable<string>[] strs=new changeable<string>[] { "ABC", "DEF", "GHI" };
foreach (changeable<string> cstr in strs) { cstr.change(cstr+"!"); }
foreach (string nstr in strs) { Console.WriteLine(nstr); }

無理矢理一行で書いたから読みにくいね。
で、changeable<T>の配列を作りました。Tからchangeable<T>には暗黙的に変換されるのでこれでいいです。
この上で、foreachで1つづつ回してもらう。
foreach内でその仮変数に代入するということは許されない。まぁ意味ないからね。
普通のstringの配列は、「甲地を見よ」などがいくつか入っていて、
foreachでは毎度、「甲地を見よ」というようなことを仮変数に入れて回してくれる。
だから内容を読むことは自由自在だ。だけど、仮変数を変えても意味はないね。
そこで、この「甲地を見よ」というものを収納したchangeable<T>のインスタンスの配列。
そこには別の「乙地を見よ」などが書いてあって、これを毎度回してくれる。
その上で、乙地を見て、乙地に書いてある、「甲地を見よ」を「丙地を見よ」に書き換えたとする。
これがchangeメソッド。確かにこれは問題じゃない。だって仮変数は変えてないから。
それでこのforeachのループが終わった後、回した配列、今回ならstrsを改めて観察する。
当然だけど、「乙地を見よ」などと書いてあるのは変わってない。
だけど乙地を見てみると、「甲地を見よ」が「丙地を見よ」と内容が変わっている。
というわけで、指すところは変えてないのに、そこから指す場所を変えて、内容を変えてしまったと。
おもしろいね。foreachをこうやって使えるとは。

LINQという名のIEnumerable革命

テストのためにVisual C# 2008 Express Editionを入れてみた。
これは.NET Framework 3.5に対応したプログラムが書けるのでいろいろやってみた。
まずデリゲートの簡略化というのが1つある。ラムダ式と言うらしい。
デリゲートの型としてFunc<T,TResult>などが導入された。

Func<double, double> v = 
t => { return 100 * Math.Sqrt(2) * Math.Sin(2 * Math.PI * 60 * t); };

数学の関数を定義するかのように簡単にデリゲートが作れると言うこと。
これはvという名前で引数にdouble1つ、返り値にdoubleを返す関数のデリゲートということ。
引数の名前を1つならt、2つ以上なら(vrms,t)のようにして、=>とやって右にいろいろ書けばいい。
{}でくくって複雑な動作を書いてもいいし、もっと簡略化して返り値を直接書いてもいい。
Func<double, double> f = t => t*2;という風にね。というかこれがラムダ式の本義ですね。
これはデリゲートの創作意欲が出てくる便利な書き方だ。
いままでも匿名メソッドってのでデリゲートは作れたけど匿名だったからなぁ…おもしろくない。
さて、これを使うことでいろいろおもしろいことが出来ます。
で、LINQというのがあるのだが、僕はこれをIEnumerable革命だと思っている。
IEnumerableは繰り返し可能、すなわちforeachできると取り決めをするインターフェース。
データベースをIEnumerableを実装したクラスのインスタンスで取り扱うというのがLINQの考えらしい。
で、データベースを操作するようにIEnumerableを操作できるという機能をたくさん搭載した。
けど、IEnumerableはインターフェース、インターフェースは動作を決めることができない。
なので抽象クラスみたいに機能が追加できるわけじゃない。
そこで考えられたのが拡張メソッドかもしれない。

System.Linq.Enumerable.Where<classmate>(foos, x => { return x.id % 2 == 0; });
foos.Where(x => { return x.id % 2 == 0; });

本来上で書くべきことを下の方法で簡略化できることなんだが、なんのことだかさっぱり。
どうもよくわからんのだがそういう特別な静的メソッドを定義してあるらしい。それを拡張メソッドと言うようだ。
拡張メソッドはとりあえず自作しないので、これを使うことを考えよう。
どうもLinqのおかげで、IEnumerableを実装したクラスに新しくいろんな機能が備わった。
IEnumerableを実装したクラスでもっともポピュラーなのは配列だな。

classmate[] foos = new classmate[] { 
new classmate(1,"浅田"), new classmate(2,"井上"),new classmate(3,"尾崎"), new classmate(4,"川上")};
var myfoos = foos.Where(x => { return x.id % 2 == 0; }).Select(x => { return x.name; });
//var myfoos = from foo in foos where foo.id % 2 == 0 select foo.name;
foreach (var foo in myfoos){
Console.WriteLine(foo);
}

というわけでこんなソースコードを作ってみました。
まず配列を作りました。classmateというクラスは自作しましたよ。本当にこんな名前のクラスメイトがいるかは知らないけど。
int型のid、string型のnameというプロパティを持ってる。ちなみにgetしかないので読み取り専用。
で、次の書き方が新しい書き方。まず型類推のvarを使っている。
まぁあんまり型類推は使いたくないけどなぁ…けど何なのか直感的じゃないもので。
後に説明するけど、ここのvarにはIEnumerable<string>を入れれば正解。
さて、件の拡張メソッドにはIEnumerableなのを加工する機能がたくさん入ってる。
それでこれはSQL文に似せて書ける。けどなんか僕は直感的じゃないからあえて使わない。
ちなみにそのSQL文に似せて書いた例はコメントアウトしてあるからわかる人は見ればいい。
なので元の拡張メソッドを呼び出して書くことにする。
この拡張メソッドにはSQL文のWHERE文に相当するWhereメソッドやらいろいろ用意してある。
で引数にはFunc<classmate,bool>なやつを用意すればいい。
この引数で与えたデリゲートでもって条件を指定するわけだ。
そんなデリゲートをラムダ式で簡単に自作できる。便利ですな。
今回は理解しやすかったから=>{}で書いたけど、この程度ならx=>x.id%2==0と書いた方がいいか。
このWhereメソッドはIEnumerableなのから条件を満たすものを選別してくれるというメソッド。
IEnumerable<classmate>を実装しているclassmate[]のときの返り値はIEnumerable<classmate>。
これをさらにSelectメソッドで加工。これもSQL文のSELECT文に由来。
引数にはFunc<classmate,TResult>(TResult任意)を渡せばいい。
今回はここから名前を取り出すデリゲートを作成してやりました。
なので、引数に渡されたのはFunc<classmate,string>、これで1つ1つ加工していくと。
もちろんもっと複雑なデリゲートを作成してもいい。名前の文字の順番を反転させるとか。
x => { char[] cs = x.name.ToCharArray(); Array.Reverse(cs); return new String(cs); }
にすればできるよ。
で、これで加工されて、返り値はIEnumerable<TResult>、今回はIEnumerable<string>ですね。
あとはこれをforeachでループに回した。
これを配列に変換することもできる。myfoos.ToArray();の要領でやればいい。
これも拡張メソッドのおかげ。
というわけでなかなかおもしろい機能が追加されたなぁと言う印象。
これはデーターベースと組み合わせてこそ便利なんだろうけど、特にそんな計画はなし。
だけど配列やコレクションの整理という意味では結構便利だなぁと思った。
まぁけど、.NET Framework 2.0では使えないのが残念。.NET Framework 3.5はいつになれば普及するのだろうか。

かっぱを着て自転車で雨の中を走る

今日は雨でした。妙に寒いですね。調子崩すわ。
さて、そんな中自転車で出かけました。
かっぱの上下着て。
普段は上しか着ないんだけど、時間に余裕もあることだしね。
まぁ確かに濡れんわな。ただ脱ぐときめんどくさかった。
上は靴を脱ぐ前に脱いで、そのへんに掛けた。これはいい。
しかし、下は靴を履いたまま脱げばいいのだが、靴が引っかかってうまく脱げない。
なので、靴を脱ぎながら足を抜くということをすることに。
確かにこれは時間に余裕がない通学時は使えないなと改めて実感した。
いや、今まであまり確かめずに使ってなかったんだよね。
若干ズボンは濡れるがそれほどでもないので。
通学途中、家から駅まで自転車で約2km、駅から学校まで徒歩で約4kmと、
結構雨というものは厄介なものです。
自転車のところではかっぱ、徒歩のところでは傘を差してますが、まぁすごい濡れるわな。
寒いしあんまりよろしくないけど、実際自転車と徒歩は融通が非常に利くので、悪い点を差し引いても十分有利な移動手段なんですよ。
雨に濡れたくはないが実際そううまくもいかないので、雨に濡れる分を減らすとかな。
あと濡れてもいいようにするとか。
カバンの中の荷物の配置を工夫して影響を減らすと。ビニールはシールドになるし。
まぁそんなわけでいろいろやってますけどね。
ちなみに雨の日は若干ゆっくり走りますが、そもそもゆっくり走ってるのであまり所要時間に差はないね。
水たまりをさっさと走り抜けるか、ゆっくり水しぶきを飛ばさないか、どちらが有利なんでしょうねぇ。
よけることが無理ならばさっさと走り抜けてるけど、たまに地雷を引くもので。

上書きすると便利になる?クラスの継承

昨日、抽象クラスであるところのSystem.IO.Streamを継承してみていろいろやってみました。

class rndstream : System.IO.Stream {
private Random myrnd;
public rndstream() {
myrnd=new Random();
}
public override bool CanRead { get { return true; } }
public override int Read(byte[] buffer, int offset, int count) {
for (int i=0; i<count; i++) {
buffer[offset+i]=(byte)myrnd.Next();
}
return count;
}
public override bool CanWrite { get { return false; } }
public override void Write(byte[] buffer, int offset, int count) { throw new System.NotSupportedException(); }
public override void Flush() { throw new System.IO.IOException(); }
public override bool CanSeek { get { return false; } }
public override long Length { get { throw new System.NotSupportedException(); } }
public override long Position {
get { throw new System.NotSupportedException(); }
set { throw new System.NotSupportedException(); }
}
public override long Seek(long offset, System.IO.SeekOrigin origin) { throw new System.NotSupportedException(); }
public override void SetLength(long value) { throw new System.NotSupportedException(); }
}

なんか例外をthrowばっかりしてるな。
まともに実装したのはコンストラクタとReadメソッドだけだな。
で、抽象クラスというのは、抽象メソッド、抽象プロパティのあるクラスのことだな。
特徴はインスタンスを作れないこと。もっぱら継承して使うクラスだと。
Streamを継承したクラスで有名なのは、System.IO.FileStreamではないかな。
まぁそんなものを自作してみたということです。
で、ひたすらランダムな値を返すというものです。
で読み込み専用なので、CanWriteはfalse一定、WriteメソッドはNotSupportedExceptionをthrow、
シーク禁止なので、CanSeekはfalse一定、シーク関係はひたすらNotSupportedException。
というわけでまともに実装したReadメソッドは見ての通り。
で、これで実際に他のStream同様に取り扱ったところきちんと動いた。
ところで、抽象クラスとインターフェースの違いってなんだろうなという話はありますね。
どうも抽象クラスは抽象メソッド、抽象プロパティだけからなるわけではなくて、
きちんとそうでないメソッドやプロパティもあるらしい。
たとえば、ReadByteメソッドは特にoverrideして定めなくてもうまく動いてくれる。
これは多分Readメソッドを利用して動いてるんだろうね。
まぁだから抽象クラスというのは穴埋めしないといけないクラスのテンプレートなのかな。
インターフェースはそんなことはできないからね。
反面インターフェースは多重継承できるから、それは特徴だよな。
関係ないことなのだが、仮想メソッドと仮想プロパティというものもあるらしい。
これはoverrideしてもいいメソッドやらプロパティという意味なのだが、はてどんな使い道なのやら。
ある例では、インスタンスの年齢を返すプロパティが仮想プロパティで、
そのクラスを継承したクラスでは、そのプロパティをさばを読むようなやつでoverrideした例があった。
で、newを付けるときと何が違うのかという話なのだが、

class foo{
protected int _age;
public foo(int age0){ _age=age0; }
public virtual int age{ get{ return _age; } }
public int agetimes2(){ return age*2; }
}
class foo2 : foo{
public foo2(int age0):base(age0){ }
public override int age{ get{ return _age-1; } }
}
class foo3 : foo{
public foo3(int age0):base(age0){ }
public new int age{ get{return _age-1; } }
}

といろいろクラスを用意して、その上で

foo2 myfoo2 = new foo2(10);
foo3 myfoo3 = new foo3(10);
Console.WriteLine("{0} {1} {2} {3}",myfoo2.age,((foo)myfoo2).age,myfoo3.age,((foo)myfoo3).age);
Console.WriteLine("{0} {1}",myfoo2.agetimes2() , ((foo)myfoo2).agetimes2() );
Console.WriteLine("{0} {1}",myfoo3.agetimes2() , ((foo)myfoo3).agetimes2() );

とすると、多分、「9 9 9 10」と表示されるはず。
virturlと書いたメソッド・プロパティに、派生クラスでoverrideでやると、元のやつを上書きしてしまって、
そして、次のagetimes2メソッドは、そのoverrideされたageプロパティを使ってやっているのでどちらも18と出てくるわけだ。
newは元のやつは上書きしないと。ただ、自分のクラスでは、元のクラスのそのメソッドを覆い隠すだけ。
だからキャストしてやるともとの動作をしたと。
そして、agetimes2メソッドは、fooクラスでの動作を考えるのだから、
newで上書きしたところで、特に値は変わらず、どちらも20と出てくると。
そんなテストでした。
newで上書きしても、元のクラスで定義された動作に影響は与えないし、元のクラスの動作を動かしたければキャストすればいいよということだな。
まぁしかし、仮想メソッドってなんの有用性があるのかねぇ。よくわからん。
以前は抽象クラスって何をしたいんだと思ってたし、
その前はインターフェースって何する物なんだと思ってたんだから大きな進歩やわな。