受験生に向けて

ちょっとだけ書いてみる。僕の知り合いの某受験生に向けて。
例えば生き方とか、考え方。そういったものに関しては、周囲の人間の言うことを聞く必要は無いし、出来ることなら自分に近い人間(例えば友人とか恋人とか)の言うことを参考にしながら、ちょっとずつ修正をしていけばいい、と思う。学校の先生の言うことは、そこまで気にしなくてもいいだろう。
例外は親くらいかな。親は、本当に親身になってくれるはずだ。もちろん例外もたくさんあるだろうけど。まあそのあたりは、自分自身で判断すればいいんじゃないかな。
でもね、受験って言うものに関しては、はっきり言って友人の言うことは信用するな。親の言うことも信用しない方がいい。一番信用できるのは、学校の先生であったりとか、塾や予備校の先生だ。この人たちは、どこまで親身になってくれるかは分からない。結局仕事の上での付き合いだし、君はその先生にとってはたくさんの生徒の中の一人だ。
そうであるのは事実だが、それでも先生と言うのはプロだ。彼らはもちろん教えるプロでもあるけれど、同時に受験と言うものに対するプロなのだ。
受験のことなら先生に聞け。そして、先生の言うことはおそらく正しい。

ところで

先日の話題だけれども。
http://www.komaba.utmc.or.jp/~plaster/diary/?040624

ちょっとだけ突っ込みいれると、

こういうことがどうして出来ないんだろうと疑問だったんですが、出来てしまうと HogeVectorをVectorとして扱ったときに困るということに思い当たり、やっと納得しました。

Vector v = new HogeVector();
v.add(new Object()); // Vectorなのだから、これは出来なければならない

getの方も同様。

Object o = v.get(n); // これもまた出来なければならない

辻褄が合わなくなりますね。つーかなんでこんなことに気づかない > 自分

これって、getの方はコンパイルが出来さえすれば可能だよね。

Object o = new Vector();

もちろん、それには問題がある・・・というか、むしろ、getの方をコンパイルできたとして、その利点がない、と言った方がいい。

そもそも、なぜ同名のメソッドを作るのか

同名のメソッドを作る理由は、わかりやすさというわけではない。もちろんわかりにくい名前を付けてもいいというわけじゃないけれども、それだけが理由じゃない。
メソッド名というのは抽象化の産物であるわけだ。

Animal animals[] = new Animal[3];
animals[0] = new Dog();
animals[1] = new Cat();
animals[2] = new Bird();

for(int i = 0; i < 3; i++){
    animals[i].move();
}

ということが出来ないと困るよね、ということである。つまりはインターフェースの存在意義もそこにある。

animals[i].move();

のところでは、animalsの中身がなんであるか(犬でも猫でも鳥でも)に関わらず出来ることである必要がある。返り値も同様で、animalsの中身がなんであるかに関わらず扱えなくてはならない。
例えば、Animal型ではObject型を返すようにしてあるhogeというメソッドがあるとする。これをDog型ではInteger型を返すようにするということができたとしよう。
しかしながら

Integer integer = animals[0].hoge();

は出来ない。

Object o = animals[0].hoge();

という扱い方「しか」出来ないのだ。出来るのは、

Dog dog = new Dog();
Integer integer = dog.hoge();

という使い方だけであって、それじゃあわざわざ同名のメソッドとして別の型を返す必要も無いよね、ということになる。他の名前のメソッドとして定義してやっても、別に開発効率に影響ないじゃん?ということ。
Javaのこの辺の考え方っていうのはすごい素敵だと思う。Javaはそれ自身としては結構完成されてる、と思う。もちろん嫌いな人もいるけど、俺は結構好きだったりする。自分で使いたくはないけどね。

ということは

これはJavaの仕様に、同じ名前のメソッドとして作る必要がないよね?と言われているわけだ。つまり、昨日の話で言うならば、NodeListはList型として抽象化して使う必要は無いよね、ということになる。
つまり、NodeListをListとして使わないということになるわけだが、ここで少し考えてみる。継承の目的とはなんだろうか。一つは上でも書いたように抽象化である。そしてこの理由は否定された。
しかしながら、メソッドをそのまま使うことが出来る、と言う点においての継承は否定されていないのだ。もしこれがPerlであれば、ラッパークラスは以下のようにするだろう。

package NodeList;
use LinkedList;

sub new{
    my $cls = shift;
    my $this = {};
    $this->{list} = LinkedList->new();
    bless $this, $cls;
    return $this;
}

sub AUTOLOAD{
    my $this = shift;
    (my $method = $AUTOLOAD) =~ s/.*://g;
    $this->{list}->$method(@_);
}

Excellent!
つまり、機能として使えるものは全て使えると言うこの美しさ。まあ、スクリプト言語でないJavaには無理な芸当ですが。
Decoratorパターンって言うらしいですね。
http://naoya.dyndns.org/~naoya/mt/archives/000892.html
が参考になりました。

いや違う

http://www.techscore.com/tech/DesignPattern/Decorator.html
インターフェースが違うと言う点で、このケースではAdapterパターンの方が正しい。
つまりは、継承して「も」よいような場合において、より柔軟に行なうのがDecaratorパターンのようです。にゃるほど。