大人の事情

id:ord さんからトラックバックをいただいた。プログラミング系の日記には初めてで、実はかなりうれしい。

http://d.hatena.ne.jp/odz/20061012

うれしい、の、だが、うーん、なんだかあまり釈然とこない。言ってもしやしないことについて文句言われてる、と最初に感じた。

とりあえず前回の話を纏めると、Javaに関して、

  1. クラスもインスタンスも「オブジェクト」だと説明出来た方がスッキリしない?
  2. でも「大人の事情」でクラスは殆どオブジェクト的なのに、オブジェクトって言えないんだ。

という話。そこに「いや、クラスってオブジェクトだろう!ホラ(以下略)」と突っ込まれた、というのがあたしの認識。

さて、なにやら行き違いがあるようだ。

まず「クラスインスタンスと言う言葉に問題があったようだ。猫的には「クラスから作られるインスタンス」つまり、Javaでいうオブジェクトを指しているつもりだった(「関数インスタンス」との比較として使った)。これが地雷だったらしい。

odz さんは、クラスファイルからロードされたメモリ上のクラスイメージを「クラスインスタンス」と呼んでるっぽい。この地雷表現のせいで誤解が誤解を呼んで、なんだかいろんな心当たりのない突っ込みをされている風に感じる。

なるほど。って、「クラスインスタンスを作らなくても生成されていて」って、んなわけない。Javaのクラスにはロードと初期化のステップがあるわけだが、すくなくともロードされるまではクラスフィールド用の領域は確保されていないはずだし、ロードされたクラスごとにクラスフィールドを持っている。つまり、クラスメソッドもクラスフィールドもちゃんとクラスに関連付けられているわけであるが、

ここの「クラスインスタンス」はもちろん「クラスのインスタンス」、いわゆるフツーのオブジェクトのつもりで私は書いた。だから「んなわけない」わけが無い。単なる不幸なすれ違いという奴だろう。

ということで、クラスフィールドがクラスオブジェクトに関連付けられていることを示すサンプルでも。

などは、あまりに明後日の方向に爆走していくので、「おーい、ちょっと待って」と呼び戻してあげたくなってしまう。くそ、あたしの文章が下手すぎるのか。(せっかくのトラックバックなのに不毛だ)

大人の事情

Javaの用語は混乱してると思う。Smalltalk由来とC++由来の用語がチャンポンになっている。クラスなんちゃら 関連は、どうやら C++ からゴッソリ引き継いだようだ。(しかし、インスタンス側の用語は軒並みSmalltalk風だ)

Java では、(インスタンスではなく)クラスそのものに紐付いたメンバを何故か 静的メンバと言う。キーワードとしてはまんま static を付ける。これは C++ から譲り受けた仕様だ。また、Javaのクラスはオブジェクトではない。クラスはあくまでクラスだそうだ。これも C++ 的だと思う。

Smalltalk ではクラスはオブジェクトなので、インスタンスオブジェクト同様、クラスオブジェクトもメソッドやフィールドを持つ。インスタンス用の定義と紛らわしいため、「クラスメソッド」「クラスフィールド」と呼び分けたというだけ。説明としては単純明快ですむ。

一方Java ではクラスはオブジェクトではないので、その理屈は通らない。static を使って作った クラス変数とクラスメソッドは、静的なクラス毎のエンティティであるとか、なんとか、説明されている。

これは、なんだか酷く回りくどく感じてしまうし、なんだか クラスとインスタンスの違いに四苦八苦している人にとっては、なんだか煙に巻かれているように感じるハズだ。



実装モデルだとか歴史的背景を「大人の事情」と揶揄したのは、それが 理解しやすさに直結しない(むしろ阻害している)と感じたからだ。いけないことかもしれないが「ホントは違うけど、クラスも一種のオブジェクトみたいなもんで、だいたい同じ事が出来るんだ」が手っ取り早いと思ってしまう。(要は、男子トイレと女子トイレの、トイレの部分を括りだそうということ)

メタクラス

しかし、odz さんが提示した 「別々の ClassLoader にロードされたクラスのフィールドは別になる」という例は面白い。

つまり、クラスメソッドもクラスフィールドもちゃんとクラスに関連付けられているわけであるが、普通に使っている場合はクラスインスタンスはクラスインスタンスは一度ロードされたインスタンスを使いまわすようになっているから、そうではないように見えるだけの話。

は、(どうも私の C の 関数のstatic変数に関する発言を、static grobal 変数と勘違いして節を感じるが、それは置いといて)ロード=インスタンス生成と考えたことはなかった。

「クラスのロード」を「メタクラスからのインスタンス(つまりクラス)の生成」と見るなら、「メタクラスインスタンス」を「クラスインスタンス」と呼びたくなってしまう気持ちもわかる*1

クラスローダを使った例は、クラスロードを「メタクラスからのインスタンスクラスを生成している」と思わせる、面白い実例だと思う。

Javaの常識?

odzさんの記事を読んで、ふとJava プログラマにとって「ロードとは、即ちメタなクラスからクラス実体を作ることである」という感覚は、非常に大切なのかなぁ、と思った。あたしゃロードはロードですよって感覚でしかない。

私は Java をたしなむ程度にしか知らない*2。日々使っているわけでないから言語仕様やライブラリに耳年増でも、結局頭でっかちの知識にしかなっていないんだよなぁ

*1:でもそれは間違いだと思うが、どうなのだろう。「クラスインスタンス」といったら、odzさんの用法が一般的なのだろうか?

*2:お仕事は(元)C#。当時C#にろくなドキュメントがないから Javaの豊富なドキュメントとノウハウを参考にしたかった、というのが Javaを勉強し始めたそもそもの動機だったり(笑)