所謂オブジェクト指向言語はオブジェクト指向してないんじゃないかというなにか
※ネタです。マジレスしない様に
※重ねて言いますがネタです。
※なんどもいい(ry
まずは http://b0r0nji.blogspot.com/2011/12/blog-post.html を読んでください。
この説明でオブジェクト指向わかった!ってなったらそれどうなんだろうと思ってしまったわけです。で、オブジェクト指向プログラミング - Wikipedia読んでみると、
相互にメッセージ (message) を送りあうオブジェクト (object) の集まりとしてプログラムを構成する技法である。
ほう、メッセージとな。さて、先の説明にメッセージがあったか?となるわけです。
オブジェクトとはなにか
多くのOOPをサポートしていると謳っている言語はこのメッセージの送受信(Message Passing)をメンバ呼び出しという形に置き換えて、概念的にはメッセージを送り合って通信しているように見せかけていると言えます。だってコンパイルすると全部線形命令列に置き換わるし。
さて、これはオブジェクト指向なのでしょうか。よくオブジェクト指向の説明に用いられる物と物の関係とか人と人の関係などをとってみても合致していないように見えます。
考えてみてください。ある物Aが別の物Bに対して作用(メッセージを送出)するとします。そのとき物AはBに対して作用はしますが、Bの中身に対して侵入的操作は行ないません。なにかBの内部状態が変化するとしたらそれはB自信が変化を加えます。さらに、現在Aが動いてるとしたらBが止まっているなどということはありません。好き勝手なにかやってるはずです。つまりAとBは独立に動いているはずです。
わかりづらかった場合は人間を例に取りましょう。誰かが何かを処理している過程であなたは心臓を停止して呼吸を停止して話しかけられるまで停止していますか?なにか自分の好きなことをしているはずです。その時だけ他人の心臓を借りて生きているわけがありません。
何がいいたいかというと、オブジェクトは独立したプロセスで好き勝手やってるというのが本来あるべき姿じゃないかと考えるわけです。
お姉ちゃんは答えなくてもいいはず
もうひとつ。主にC++のようにコンパイル時に該当するメンバがなかった場合にエラーになる系の言語についてです。
このエラーになるということが何を意味しているかを考えます。
- しゃべろうと思った相手はそのメッセージを受け取らなければならない
- メッセージを受け取ったことに対して何かしら反応を起こさないといけない
という制約が発生します。
これはお姉ちゃんの例に当てはめると、
ある人が「ぐへへお姉ちゃんパンツ何色」と質問する、と同時に暗黙の脅迫である「話聞けや」と「答えろや」が含まれる
と言うことになります。
答えたくなくて無視したい場合でもcaller側から脅迫されているので答える他ありません。答えたくないがために「はいてません」などと言ってしまうと更なる危険が待っていることでしょう。
この人権を無視したやりとりを紳士である皆さんは黙認できますか????たとえお姉ちゃんが警察を呼んだ(throw)としてもその瞬間ある人はcatchしてどこかに連れ去ってしまうでしょう。
真のメッセージパッシングによるOOPは無視できる
お姉ちゃんの人権を守るためにも正しいOOPを考える必要があります。現在問題に挙がっていることは
- 独立したプロセスでオブジェクトが動いて欲しい
- プロセス間でメッセージのやりとりをする必要がある
- メッセージを選択して受取りたい(無視できたい
ぐらいでしょうか。
これを解決するのが Erlang です。Erlangは並列指向として知られていて、オブジェクト指向に関する文言は1言も見つかりません。しかし最もOOPを再現できるのがErlangなのではないかと考えます。
Erlangは並列指向プログラミングという名からも想像できる通り、並行並列な記述を得意とする言語です。言語の設計はActorモデルをベースとしています。
新たなプロセスを作るのはspawnを使い、メッセージの送信には ! を使います。メッセージの受信にはreceiveを使い、receiveで受信するメッセージはパターンマッチにより取捨選択できます。
ちょっと適当なのを書いてみましょう。
-module(pants). -export([main/0]). main() -> Oneechan = spawn(fun() -> oneechan(shimapan) end), Boyfriend = spawn(fun() -> boyfriend(Oneechan) end), Aruhito = spawn(fun() -> aruhito(Oneechan) end), Oneechan ! {boyfriend, Boyfriend}. oneechan(Color) -> Boyfriend = receive {boyfriend, B} -> B end, oneechan(Color, Boyfriend). oneechan(Color, Boyfriend) -> receive {guhehe_oneechan_pants_naniiro, Boyfriend} -> Boyfriend ! {pants, Color} end, oneechan(Color, Boyfriend). boyfriend(Girlfriend) -> Girlfriend ! {guhehe_oneechan_pants_naniiro, self()}, Color = receive {pants, C} -> C end, io:format("Boyfriend: ~w~n", [Color]). aruhito(Oneechan) -> Oneechan ! {guhehe_oneechan_pants_naniiro, self()}, Color = receive {pants, C} -> C end, io:format("Aruhito: ~w~n", [Color]).
これを実行してみましょう。
$ erl Erlang R13B03 (erts-5.7.4) [source] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false] Eshell V5.7.4 (abort with ^G) 1> c(pants). ./pants.erl:7: Warning: variable 'Aruhito' is unused {ok,pants} 2> pants:main(). Boyfriend: shimapan {boyfriend,<0.43.0>} 3> q(). ok 4>
素晴らしい!boyfriendのみパンツの色を聞くことに成功しました!ある人ざまぁwwwww
まとめ
Erlang使いましょう。 (<-力尽きた