はてなキーワード: ポリモーフィズムとは
オブジェクト指向とかかっこいい言い方をしても無駄だ。従来の構造化プログラミングから進歩したことなど一つもない。オブジェクト指向がなぜダメであるのか、それを今から話すぜ。
1. データと処理をまとめるという発想。
データと処理をまとめてクラスとして置くという発想がある。しかし、このようなことをしなくとも、モジュールという単位で利用データと処理の集合をまとめればよかったので、クラスを使う必要はない。しかもクラスはインスタンス化のときに、不要な情報まで持ってくるのでメモリ効率が明らかに悪い。コンピュータが進化しているからメモリのことはあまり考える必要がないとはいえ、必要ない処理をまとめて閉じ込めるのは無駄が多い。なぜクラスという名詞で概念分類できると考え始めたのかは不明だが、アルゴリズムとデータ構造という構造化プログラミングの手法を、クラスと型というパラダイムに変換することで型にうるさいC++馬鹿を生み出し、彼らが発狂することになってしまった。しかもデータと処理にわざわざ依存関係を持たせて、変更に対する柔軟性を失わせている。
2. 継承
継承によって既存の構造を持ってこようとする必要性が全く無い。それどころか、継承を使うことによってプログラムがスパゲティ化し、依存関係のグラフがややこしくなってしまう。継承など使わず、必要な情報はスコープの限られた共通の変数、または関数の引数として用意しておけば良い。もしクラスをどうしても使いたければ、共通のインターフェイスをもたせたほうがマシである。インターフェイスを使えば、クラス利用者が意識すべきpublicメソッドがなんであるか把握できる。
3. カプセル化
オブジェクト指向の中で役立つ概念はカプセル化だけである。しかし、カプセル化はクラスなしで構造化プログラミングの方法で実装できる。pythonでは、モジュールの中でアンダースコアから始まる関数を用意しておけば、それがprotectedやprivateと似たように機能させることができる。オブジェクト指向がなぜカプセル化が独自の概念だと言い始めたかは謎。
4. ポリモーフィズム
同じ名前のメソッドを、入力に応じて処理の内容を変える。このようなことはオブジェクト指向などと誇大宣伝をするほどのことでもない。構造化プログラミングで似たようなことができる。
これまでいろいろな書籍やサイトから情報を得てきて、オブジェクト指向のプログラムを、「知識とスキルを持った職人をいっぱい雇ったプロジェクト」というように理解している。
極論を言えば、オブジェクト指向=擬人化思考というように捉えているけれど、この理解はどの程度あっているのだろうか?
とすると、
職人は、会社の指示によって働き、持っている知識とスキルを使って仕事をする。
知識やスキルは、各職人が会社に指示されたマニュアルを読んで覚える。
とか
オブジェクト指向が特に有用なのは、特に複数の会社と協力して作業する場合である。
そのような大規模なプロジェクトであるならば、各企業の職人一人一人に指示するよりも、マニュアル一つで指示した方が簡単だし、間違いが少ない。
オブジェクト指向の三大概念として、いろいろな媒体で紹介されている「継承」「ポリモーフィズム」「カプセル化」も、それぞれ「一つのマニュアルを用意して、職人に利用してもらいやすくする」「各職人は、自分にとって必要なマニュアルの一部を読んで知識とスキルを手に入れる(ここの理解は自信がない)」「マニュアルは、職人によって勝手に書き換えられないようにするべき」みたいな感じでなんとなく理解している。
ただ、根本のオブジェクト指向がよくわかっていないため、これが合っているのかもわからない。
のだけれど、なんとなく色々勉強してきて、複数人とプログラムを組むとか、大きなプロジェクトとかでもない限り理解していなくても問題なさそうなので、回収率100%を超える競馬プログラムが出来上がるのを夢見て寝ます。
言ってないけど。
Cから派生したCやJavaなどでやってるのはオブジェクト指向プログラミング。
クラスというものを作って、「カプセル化」、「継承」、「ポリモーフィズム」を三本の矢にして
これを提唱しているのはオブジェクト指向プログラミングを日本語で解説しているWikipediaなので間違いない。
現在の日本人に対してオブジェクト指向とは何かと問えばこれのことなので、これさえ押さえておけば会話に問題はない。
なまじっか真のオブジェクト指向に精通していると、英語版wikipediaでオブジェクト指向を学び、smalltalkなんかかじった日には、現代日本におけるオブジェクト指向がいかに偽物かわかるだろうが、奇異にみられるのはあなた自身であることを付け加えておく。
16歳 はじめてのエロサイト このときPCの壁紙が金髪お姉さんのオ○ンコ画像になって戻せなくなり、情報セキュリティに興味をもつ
16歳 はじめてのCプログラミング 学割でVC++を買うがまったくわからず挫折
16歳 はじめてのVBプログラミング 学割でVBを買い、メモ帳をつくったところで、それ以上のことができなくなり飽きた
18歳 HSPという言語を知り、ゲームをつくったり、エロ画像をEXEのバイナリに含めて隠したりした
20歳 Javaを触っているうちにポリモーフィズムの概念がわかってきた、ここからプログラミングが急速に伸びた
21歳 IE6があまりにもアレなので、Javaでタブブラウザを作り、エロサイト巡りをはかどらせる
〜24歳 なんやかんやで Java, PHP, C++, Python, VB6, VB.NET, C#, Oracle, MySQL, PosgreSQLを覚える (このあたりでOracle Silver,応用情報をとる)
〜30歳 なんやかんやで Go, Obj-C, Swiftを覚える 機械学習に興味を持つ
31歳 エロ画像収集AIが完成したが、風俗にはまったため活用されず
32歳 Reactで爆速エロサイトをつくったところ、なぜか東南アジアで人気になる。AWS教では月間1200万PVを月4000円でさばける。
引数がA,B,C,D,Eあるとして
A,Bだけ渡したら、内部でC,D,Eを自動的に解釈するメソッドが作りたかった
これ、例えば
func hogeAll(A a, B b, C c, D d, E e) {
}
func hoge(A a, B b) {
}
んだけど、ABCDE全てに対して有/無のメソッドを全て定義すると果てしなくなる
実際にこれはよくやられると思う
HikisuClass hikisu = HikisuClass.create(a,b) // これで内部で自動的にc,d,eを解釈する
でもメソッド一個のためにクラスを作るのってクソ面倒だなと思う
もう一個方法があるとしたら、Classに値を入力したあとメソッドを実行する方法だ
hoge.a = a
hoge.b = b
hoge.do()
hoge(a,b,null,null,null) みたいなことになりそう
ちなみに何でそういうことをしたいかと言えば、自然言語がそうなってるからだ
大抵の引数が省略されるし、省略されたりされなかったりする、非常に柔軟なんだ
もちろん受ける側の作り込みが大変になるが、ちゃんとリーダブルに作ろうとしたらそっちのほうが良いんじゃないかと思える
引数のoptional,requireを指定できればもっと良い
これってポリモーフィズムあたりの話か?
___
追記:
あ、DIコンテナみたいな話かな
でも結局煩雑だし使いたくない
システムを定義する場合、そのシステム「どのような機能」を持つかと、その機能を「どのように実現する」か。という二つに分かれる。
前者は、アプリケーションドメインと呼び、後者をソリューションドメインと呼ぶ。
抽象化された論理的な設計はアプリケーションドメインに含まれ、ソリューションドメインは言語や環境に適応させた実体になる。
少し前、システムはソリューションドメインのみを実現したモノとして扱われ、そこにオブジェクト指向を組み合わせることが多かった。
ただ似ているという理由で、継承が行われることが多発した。「オブジェクト指向がそのまま、ごちゃまぜになって散り散りに流出した。」
というか、そもそもアプリケーションドメインって考えが無かった。それが設計書との乖離を産みスパゲッティコードが増えた。
オブジェクト指向で最初に学ぶ継承が、ポリモーフィズム(多様性)を実現するための1つの特性でしかないのに
「継承のためにオブジェクト指向を使っても良い」という誤った考えが、勘違いの原因だろう。
この問題は、最近では結構認知されてるのだが、実際の現場では、打開策を模索中な場合が多い。
近年のアプローチは、システム上でもアプリケーションドメインは表現されるべきという考えである。
打開策としては、このアプローチによる実績を増やしていくこと。
「ごめんください」
「何や今時分、おお、お前か。まあ上がり」
「どっちの足から上がりましょ」
「お前と掛け合いで落語やる気はない。早よ、上がれ」
「へへへ。ほな失礼します」
「失礼は毎度のことやんけ」
「何です」
「いやいや。ほんで何やねん」
「ほおん、なるほど。で、その心は」
「別に謎かけやないんですが、まあ、しんどいちうことと、ええ歳していつまでもこんな仕事してたらあかんなあと思いまして」
「せやなあ、今年は蟹の水揚げが不調やしな」
「いったい何なんですか、ぼくの職業は。多喜二ですか」
「軽い冗談や」
「まあ、ほんまにそれくらい厳しい労働条件ですけどね。いっそアカになったろか思いますよ」
「ほな、俺、公安ね」
「なんで今からごっこ遊びせなあきませんねん」
「せやから軽い冗談や、言うてるやろ。で、辞めてどうするねん」
「何やて」
「ほら、ぼく、ワードやエクセル使うの得意ですやん」
「ワード……、エクセル……」
「何ですか」
「お前、キーパンチャーにでもなるつもりか」
「何ですか、そのキーパンチャーて」
「それはやな、君」
「なんでいきなり噺家口調になるんですか」
「シーモンキー。滅茶滅茶遠いし」
「とにかく俺が言いたいのはやな、お前ほんまにワードやらエクセルやら云々でコンピュータ関係の仕事に就けると思てるんか、ちうこっちゃ」
「ああ、判りました。いつもの口癖ですね。プログラム作れん奴はコンピュータ触るな、とか、ユニックス判らん奴はネットに出てくるな、とか」
「まあ、そういうこっちゃ」
「でも、コンピュータ関係の仕事には絶対にプログラムの知識が必要なんですか」
「んー、そういうこともなかろうけどな。まあでも、ソース読めへんSEとか管理者っちうのはちょっとぞっとするわなあ」
「実はね、そうやろうと思ってぼく最近プログラムの勉強してますねん」
「ほほう」
「あっ、いきなり薄笑い浮かべてますやん。滅っ茶馬鹿にしてるでしょ」
「C言語です」
「くくく」
「あっ。腹立つ、このおっさん」
「くくく。まあ、しっかり頑張りたまえよ」
「何か悔しいなあ」
「で、どないして勉強してるねん」
「へへへ。ちゃんと例のやつ買ったんですよ」
「例のやつて何やねん」
「いつも言うてはるやないですか。バイブルやて。R&Bですよ、R&B」
「R&B」
「そうです」
「K&Rやろが」
「そうそう。そうとも言う」
「そうとしか言わんちうねん」
「今どれくらいまで進んでるねん」
「それ、滅茶苦茶初めのほうやんけ」
「お前、パール書けたっけ」
「えっ。あれって自作やったんか」
「ちゃいますけど、ちゃあんとタイトル書き換えて使ってますやん」
「……」
「頭抱えてどないしはったんですか」
「そうです」
「お前な、何かをものすごく誤解してるか、世間をものすごく舐めてるかのどっちかやな」
「えへへ。そうかな」
「あかんわ。褒められたと思とる」
「C言語覚えたら次はシーインクリメントですわ」
「なんやて」
「シーインクリメント」
「そうです。何か変ですか」
「まあ『++』は確かにインクリメント演算子やけどな。普通はCプラプラって言うやろ」
「変ですやん、そっちの方が。大のおとなが『ぷらぷら、ぷらぷら』言うて」
「確かに宮沢章夫もそう書いてたけどな」
「お前なあ、自覚ないやろけど、それはものすごく難しい質問やで。一言で、て」
「けち臭いこと言わんと教えてくださいよ」
「またまたあ、わざとややこしい言い方して煙に巻こうとしてるでしょ」
「むかむかむか。そしたら言うたるわい。C++ちうのはやな、要はクラスの概念を実装したもんで、クラスちうのはインスタンスをうんたらかんたらで、継承とオーバーライドがこーたらで、ポリモーフィズムがなんたらで、隠蔽がどーたらで、うらうらー」
「……」
「……」
「はあっ。はあっ。どうや、参ったか」
「うーん。何かよう判りませんわ」
「なんか難しそうやから、C++やめて次はJavaにしますわ」
「ぎゃふん」
ていうか当たり前。
いやもちろん問題なんだけどね。
現場にいる私にとっては同僚のスキルが低いのは当然問題なんだし私自身へぼであることは問題だけれども、そういう次元の話じゃなくて。
はてななど見てると、まるで何か、プログラミングへの情熱に燃えて努力を惜しまずスキル向上してる人がプログラマって職業に付くのがしかるべき姿であって、ポインタもポリモーフィズムも理解できない(理解しようと努力もしない?)間抜けがプログラマになるなど言語道断であり、10000行のメソッドが作られるような悲劇はなんとしても避けなければならない、って雰囲気だけど。
いや悲劇は避けられたほうがいいけどさ、あのさ、「その仕事に熱意もないし能力もない、特になんもない人がその仕事をしてる」っていう状況は、しごく当たり前なのであって、むしろ、「自分の好きなことを仕事にして自分の能力を伸ばして社会に会社に貢献して自己実現しましょー」っていう思想のほうがよっぽど異常だから。
仕事にしたいような好きなことなんて、無いでしょ。ふつう、無いでしょ。
なんとなく学校出て、働かなきゃなー、って思って、なんとなく働くの。そんだけ。
で、たとえば飲食店に行ったら、いかにも接客業に向いてない感じのぼさーっとした奴が店員やってたりするでしょ。これ、普通。
世の中、たとえばタンポポを刺身に仕事があって、タンポポ大好きでその仕事するやつもいれば、なんとなく就職してタンポポ乗せてる奴もいる。
そんで、タンポポ乗せるのうまい奴とか下手な奴とかいる。それだけ。
もしかしたらソフトウェア開発ってのは崇高なる職業であってセミの死骸を裏返しにする仕事とは格が違うのかもしらんけどさー。
たいした変わらんって。
人間だいたいほとんどバカ。バカばっかり集まって社会ができててもなんとかなる。これ素晴らしい。
プログラミングできないけどSE、なんてねえ、まあ、とりあえずパソコンに向かって座ってて給料もらえるんだから、しめたものですよ。
あいつ全然仕事できないっていうか俺の書いた美しいコードを汚してるだけなのに、俺と同じ給料もらいやがって、ってそれ、賃労働に囚われ過ぎ。
がちがちに仕事できるやつだけ集まってる職場なんて息苦しいですよー。
そんなこんなで明日も日が昇るのだから、すーぱーはっかーにもFizzBuzz書けないあいつにも等しく感謝して、だらだら生きなさい。
あれは私がまだ大学助手をしていたころだから3年ほど前のことだと思う。
私の勤めていた大学(情報系)では「プログラミング研究会」みたいなサークル活動が行われていて
プログラミングの講義を受け持っていた私はそのサークルにちょくちょく顔を見せるようになっていた。
そこにはとびっきりかわいい女子学生が一人いたのだけれど、その子はゲームが大好きで
「自分でもゲームが作りたい」と一念発起してゲームコンテストに作品を出品することになった。
しかし、彼女はプログラミングの講義(Java)を1年くらい受けているものの、
本格的なモノを作った経験がなく、ひとりでは行き詰まりをみせているようだった。
彼女はひとりでいることが多く、パソコンに向かって黙々とプログラムを書いているのをよく見かけた。
それを気にかけていた私はたまに彼女をランチに誘うようになり、彼女の方もしだいに私に打ち解けてきた。
私たちはだんだんと仲良くなっていった。私は彼女のキュートな笑顔に魅了されていった。
ある日、彼女が私のもとにやってきて、もじもじと顔を赤らめながら上目づかいにこう言った。
「先生、頼みごとがあるんですけど・・・」
「なんだい?」
これから恋の話が始まるのを期待したあなたは別のページを読んだ方がいいかもしれない。
これから始まるのはプログラミングの話だ。
その日から毎日のように彼女は私にメッセンジャーでプログラミングの相談を投げかけてきた。
彼女は大変優秀で、私の教えるプログラミングテクニックをみるみる吸収していった。
私は彼女の才能に驚き、彼女が将来優秀なプログラマになるであろうことを確信した。
しかし、ときおり彼女が優秀であるがゆえの面白い逆行現象が起こったのだった。
ある日、私は彼女がメモリを意識してプログラミングをしていないことに気づいた。
Java ではメモリを意識する場面というのは少ないが、まったく無いわけではない。
私は彼女にプログラムがメモリを無駄に使っているということを指摘した。
しかし、よく聞いてみると、彼女はメモリ=ハードディスクくらいの感覚しか持っていないことがわかった。
驚かないでほしい。
私の経験上、情報学部の学生の半分以上がメモリとハードディスクの区別がついていない。
それを知っている私は落胆することもなく、落ち着いて彼女にメモリの説明をすることができた。
彼女は私の説明を聞き「よくわかりました」と、とびきりキュートな笑顔を見せた。
しかし、翌日、彼女の書いたコードを見てがく然とした。コードが次のように変更されていたのである。
for (int i = 0; i < MAXHOGE; i++) { doSomething(i); } for (int i = 0; i < MAXFUGA; i++) { doSomething2(i); }
↓
int i; for (i = 0; i < MAXHOGE; i++) { doSomething(i); } for (i = 0; i < MAXFUGA; i++) { doSomething2(i); }
彼女はこのコードを私に見せながら、相変わらずのキュートな笑顔でこう言った。
「このほうが使うメモリが少ないですよね!」
ゲームコンテストの締め切りが近くなってきて、実際彼女はよく頑張っていたのだが、
どうしても間に合いそうになかったので、私もコード書きを手伝うことになった。
とある部分を書いていたとき、重複したコードを見つけたので Template Method パターンを使って書き直した。
Template Method パターンというのが何かというと、同じことをするコードがいくつもの場所でばらばらに書かれないように
一つのクラスにだけ書いて、それを継承して使いまわすという手法(デザインパターンの一つ)だ。
私はこの手法を彼女に教えようとは思わなかった。
なぜなら、彼女は継承だとか委譲だとかポリモーフィズムとかがよくわかってないのだ。
驚かないでほしい。
私の経験上、情報学部の学生の99%が、その、ポリホーなんとかが分かってない。
しかし、彼女はそれに気づいていた。
彼女は私のコードを自分で解析し、新たなる発見を独力でしていた。
重複したコードがあればそれを徹底して継承で解決しようとしている。
そう、差分プログラミングだ。
差分プログラミングの正式な定義は知らないが、彼女は IS-A 関係のない継承を使ってしらみつぶしに
重複コードを書き直していた。
そのコードを見せながら、天使のような笑顔で彼女はこう言った。
「こうするとコードの量が減りますよね!」
私がこの文章で言いたいことは、知の高速道路を渡ってきた若い優秀なプログラマは
ときおり妙な退行現象を起こすということだ。
それは普通の道を通ってきた古い世代にとっては実にみょうちきりんなことに思えるかもしれない。
しかし、それは彼らなりに理由があってのことであり、馬鹿だからやってるわけではない。
彼らは優秀であるがゆえにそういったことを起こすのだ。
そして彼らは優秀であるがゆえに、自分が間違っていることを理解するのも速い。
もし、あなたのまわりで若いプログラマが逆行現象を起こすのに遭遇したとしても、
どうか暖かく見守ってほしい。
上で紹介した2件に関しては、彼女にはそのあと説明をして理解を得ることができた。
しかし我々はそれで油断してはならない。
いつか彼女はその可愛らしい顔をにっこりとほほ笑ませながらこう言うかもしれないのだ。