またまたいろいろな方からご意見をいただいております。ありがたいことです。
ここでは、そういったご意見に対する私なりの回答を書いていきたいと思います。
ある方からメールをいただきましたので、以下に掲載します。
自己紹介や結びの言葉は多少削ってあります。ご了承ください。
私は、オブジェクト指向云々には程遠い、マイコンのファームかきです。 単なる興味で突っ込むので、あさっての意見があるかもしれませんが、 お許しください。 ファームやが考えることですが、オブジェクトの例として、たとえば、 ネットワークカード(チップ)というのはどうでしょうか? 同じチップが複数ある場合、互換チップが混じっている場合では、 (うまく説明できませんが、)オブジェクト指向的な考えを自然に 皆さんしているのではないでしょうか? 実際に、チップの制御をどこからでもできてしまうとよろしくないし、 かといって固めてしまうと使えないし、、、、。 うまく説明ができないので、この辺で。(文才がないというか、 はっきりわかっていないというか、、、、。) 今後も色々なものの(うまい)説明を期待しています。よろしくお願いします。 #ハードもソフトも同じに扱えるのが、私のながーい夢です。
返信はこちら。
前橋です。ご意見ありがとうございます。 >ファームやが考えることですが、オブジェクトの例として、たとえば、 >ネットワークカード(チップ)というのはどうでしょうか? オブジェクト指向において、オブジェクトをハードウエアの部品に たとえる例というのは昔からあったはずですし(Objective-Cの SoftwareICとか… 使ったことはないんですが)、発想としては 自然だと思います。 でも… プログラミングの世界のオブジェクト指向と違って、 ネットワークカードの場合、個々のチップが、本当に並列に 動いているんですよね。むしろこっちの方が真のオブジェクト 指向なのだろうとは思いますが。 >同じチップが複数ある場合、互換チップが混じっている場合では、 >(うまく説明できませんが、)オブジェクト指向的な考えを自然に >皆さんしているのではないでしょうか? これは継承でしょうか。 この場合、「hoge」というチップと「スーパーhoge」というチップが あったら、きっと「スーパーhoge」の方が後発で機能が増えていて、 「hoge」の上位互換になっていると思うんですが、この場合、 「hoge」の方が「スーパークラス」であるという。 これは用語が変なような気もしますが、用語は所詮用語なので 気にしてもしょうがないことなんでしょうね。 ちゃちゃみたいな返信ですみません。 # ハードは詳しくないのでよくわかってないだけというか… >#ハードもソフトも同じに扱えるのが、私のながーい夢です。 ハードの方が圧倒的にバグが少ないように見えます。 ソフト屋としては、がんばらなければいけませんね。
ある方からメールをいただきましたので、以下に掲載します。
自己紹介や結びの言葉は多少削ってあります。ご了承ください。
「オブジェクト指向再入門」を拝見させていただきました。 いろいろツッコミどころが多いのですが、全体の論旨は面白いと思います。 ところで「「カプセル化」という幻想」の項であげられたPointクラスですが、 項の論旨は別にしても、設計がちょっと変なのではないかと思います。 というのも、private変数にダイレクトに対応するset/getメソッドを 機械的に定義するのは、実はカプセル化でもなんでもないわけで、それに対して 「このPointクラスのx, yをprivateにして、 publicなgetX(), getY(), setX(), setY()を付けることに、 いったいどれほどの価値があるでしょうか 」 と言われても「だってそれカプセル化じゃないし」なのではないかと。 カプセル化とは「実体と表現を分離せよ」というのが論旨であって、 アクセス権がどうとかそういう話ではないわけです。 例のPointクラスなら、 「二次元座標」という実体に対して、「極座標」という表現をくっつける事ができます。 この場合、 「X,Yはpublicだから直接アクセスしていいけど、極座標はgetRadius/Angleつかってね」 ときたら、これはオブジェクト指向といえないでしょう。 まあ「データを保持するためのクラス」と断ってますから、 誤解はされていないと思うのですが、例としては不適切かと。 「データフィールドはprivateを信条としてsetter/getterを使え」なる オブジェクト指向鉄の掟は、 おそらくこういった表現レベルのポリモフィズムを睨んだものなので、 入門書の「とりあえずprivate」方針は必ずしも間違っていないでしょう。 少なくとも、怪しげなダイレクトアクセスが跋扈するクラスがあちこちを 侵食するよりはずっとマシだと思われます。
返信はこちら。
前橋です。ご意見ありがとうございます。 >「オブジェクト指向再入門」を拝見させていただきました。 >いろいろツッコミどころが多いのですが、全体の論旨は面白いと思います。 どうもです。ツッコミを歓迎します。 >ところで「「カプセル化」という幻想」の項であげられたPointクラスですが、 >項の論旨は別にしても、設計がちょっと変なのではないかと思います。 >というのも、private変数にダイレクトに対応するset/getメソッドを >機械的に定義するのは、実はカプセル化でもなんでもないわけで、それに >対して >「このPointクラスのx, yをprivateにして、 publicなgetX(), getY(), setX(), >setY()を付けることに、 いったいどれほどの価値があるでしょうか 」 >と言われても「だってそれカプセル化じゃないし」なのではないかと。 全くその通りです。私もそう思っています。だから私も「カプセル化にも 何にもなっていません。 」と書いているわけです。 >カプセル化とは「実体と表現を分離せよ」というのが論旨であって、 >アクセス権がどうとかそういう話ではないわけです。 同意します。 データ隠蔽ではなく実装隠蔽だ、という言葉があって、まあこれも 言葉遊びの匂いがしないでもないですが、同様のことを言っているように 思います。 問題は、上のようなPointクラス(や、それと同レベルの「setter/getterを 付けただけ」のクラス)をもってして、「カプセル化」としている入門書がある、 ということです。「Javaの格言」の第1章のタイトルは「カプセル化」ですし、 getX(), getY(), setX(), setY()を付けたPointクラスの実装を「よい例」と して挙げています(BankAccountの方の例はわかるんですが)。 >例のPointクラスなら、 >「二次元座標」という実体に対して、「極座標」という表現をくっつける事ができます。 ところでやや話がずれるのですが、 たかが int型のx, yを持ってるような「Pointクラス」に対して、 「極座標」なんてものを持ち込む可能性を考えるのは、まず確実に 無駄であり、それをちゃんとわきまえておかないと「泥沼の設計地獄」に 陥るのではないでしょうか。ていうかそんな例は何度も見たような。 私もやっちゃった経験ありますし。 >この場合、 >「X,Yはpublicだから直接アクセスしていいけど、極座標はgetRadius/Angleつかってね」 >ときたら、これはオブジェクト指向といえないでしょう。 実用上不便があるかはよくわからない(だから、100万行のソースを 書いちゃってから極座標が必要になったら、「X,Yはpublicだから直接 アクセスしていいけど、極座標はgetRadius/Angleつかってね」と私も 言うかもしれない)ですが、少なくともかっこ悪いですよね。 >「データフィールドはprivateを信条としてsetter/getterを使え」なる >オブジェクト指向鉄の掟は、おそらくこういった表現レベルのポリモ >フィズムを睨んだものなので、入門書の「とりあえずprivate」方針は >必ずしも間違っていないでしょう。 ここで言う「表現レベルのポリモフィズム」というのは、「もしかして 極座標で扱いたくなるかもしれないし」ということですか? その可能性があるのならそのような設計にすべきだし、まあ絶対に ないと思えるなら考慮する必要はないと思います。 x, yがintになってるようなPointでは、極座標を扱う事態になるとは ちょっと思えません。 私が言いたいのは、「何らかの規則に従うのなら、その意味をちゃんと 考えて、メリットとデメリットを秤にかけてからにすべきだ」ということです。 私自身、Pointクラスに関して、x, yをpublicにするとは言っていません。 Javaならimmutableにします。オブジェクトを参照でしか扱えないJavaでは、 簡単にdynamic aliasingが起きるので、変更できると怖いです。 プロジェクトのコーディング規約としてなら、 「大規模開発ではアレなプログラマもいるから、「とりあえずprivate」と 規則で縛ってしまえ」 というのもひとつの指針ではあると思います。でも、自分自身が 「アレなプログラマ」でいたくないのなら、盲目的になるのはいかがなものかと。
補足:今読み返すと、『自分自身が「アレなプログラマ」でいたくないのなら、 盲目的になるのはいかがなものかと。』という部分が、このメールを書いた方に 直接向けた言葉のようにも取れますね。 すみません。そういう意図ではなく、私を含めた一般論として 「何らかの規則に従うのなら、その意味をちゃんと 考えて、メリットとデメリットを秤にかけてから」ということができないと、 「アレなプログラマ」の仲間入りでは? ということが言いたかったわけです。 誤解を招きそうな表現でした。失礼しました。
皆様からのご意見というわけではないのですが、掲示板でちょっと話題に出した 「dog.sendMessage("bark", new Object[] {});」と書けるクラスの実装です。
Id.java import java.lang.reflect.*; class Id { public Id sendMessage(String methodName, Object[] args) { Class[] classes = new Class[args.length]; for (int i = 0; i < args.length; i++) { classes[i] = args[i].getClass(); } Object ret = null; try { Method method = this.getClass().getDeclaredMethod(methodName, classes); ret = method.invoke(this, args); } catch (Exception ex) { ex.printStackTrace(); System.exit(1); } if (ret == null) { return this; } else { return (Id)ret; } } }
Dog.java class Dog extends Id { void bark() { System.out.println("わん"); } }
Main.java class Main { public static void main(String[] args) { Id dog = new Dog(); dog.sendMessage("bark", new Object[] {}); } }
dog.sendMessage()の部分だけ見れば「メッセージ送出」っぽいのかも知れませんが、 少なくとも、これをC上がりのプログラマに説明するのなら、 やっぱり「関数呼び出し」でよいと思います。 メソッドを名前から動的に探すだけで、やってることはやっぱり、 (意味的に言っても)関数呼び出しなんですから。
このページに対してご意見・ご質問・ご感想等をいただいた場合、 公開することがあります。