抽象データ型とメッセージ・パッシングー2つのオブジェクト指向

アラン・ケイが当初考えたオブジェクト指向は「メッセージ・パッシング」を強調するものでしたが、その後、データ型の実装を隠蔽する「抽象データ型」の思想がオブジェクト指向に合流し、現代では2つの異同が分かりにくくなっています。その異同を理解しやすく説明する試みです。
11
sumim @sumim

なぜ人は、出自も目的も異なる2つの「オブジェクト指向」を、こうも無茶をしてまでひとつにまとめたがるのか?

2018-06-27 17:31:54
sumim @sumim

「オブジェクト指向とは何ですか?」への自分の回答 jp.quora.com/%E3%82%AA%E3%8…

2019-02-17 06:10:37
sumim @sumim

@namachan10777 「オブジェクト指向」には、クラスを使ってデータ型を定義するアイデアと、メッセージで決定を遅延するアイデアの2つがあります。初期の頃、後者は非同期ではないながら本当にメッセージを送っていて、それをヒントにメッセージによるプログラミングを非同期処理の問題解決に応用したのがアクターです

2018-12-09 08:37:06
杉本啓 @sugimoto_kei

(OO①)抽象データ型のオブジェクト指向とメッセージ・パッシングのオブジェクト指向は、実現する機構の面では似ているので、違いが分かりにくい。Javaなど、今日の主流的な言語を使う僕らは、機構の面からではなくオブジェクトの使い方の面から考えた方が、両者の違いを理解しやすいかもしれない。

2020-02-22 20:46:26
杉本啓 @sugimoto_kei

(OO②)2つの視点が違いを理解するカギと思っている。一つ目は、メッセージの送り手と受け手の関係性。 抽象データ型では、メッセージの送り手は受け手のオブジェクトの「ユーザー」であって、受け手に依頼した仕事が厳格に実行されることを期待する。その期待が「契約」として表現される。

2020-02-22 20:47:28
杉本啓 @sugimoto_kei

(OO③)抽象データ型である Stack に何かの値を push したら、その値がスタックに積まれ、次の pullで取り出されることが期待される。こんな風に、厳格に規定された仕事を受け手が引き受ける、というメンタルモデルが、抽象データ型の根底にあると思う。

2020-02-22 20:48:20
杉本啓 @sugimoto_kei

(OO④)一方、メッセージ・パッシングのオブジェクト指向では、メッセージを送られた側が何をするかは、基本的に、送られた側の判断事項である。 たとえば、Observer パタンで、Subject から変更発生を通知された Observer が何をするのかは、Observer の自由であって、Subject 側は関知しない。

2020-02-22 20:49:19
杉本啓 @sugimoto_kei

(OO⑤)別の例を挙げよう。Commandパタンで、Command の execute() を呼ぶ側は、実際に何が実行されるのか、ふつう関知しない。Visitorパタンで、Visitor 側が何をするかは、Visitor の問題であって、呼び出す側は関知しない。こういう関係性は、メッセージ・パッシング的だと思う。

2020-02-22 20:50:26
杉本啓 @sugimoto_kei

(OO⓺)もう一つの視点は、ポリモフィズムに対する態度だ。抽象データ型のオブジェクト指向では、本当はポリモフィズムは必須ではないと思う。というのは、抽象データ型において重要なことは、インターフェース(契約)と実装を分離することであって、振る舞いを動的に差し替えることではないからだ。

2020-02-22 20:52:03
杉本啓 @sugimoto_kei

(OO⑦)抽象データ型のオブジェクト指向では、むしろ、実装を差し替えたとしても振る舞いに影響を与えないことが強く要請される。List という抽象データ型を実装する ArrayList と LinkedList は、振る舞いに関して差がないことが重要なんだ。

2020-02-22 20:53:20
杉本啓 @sugimoto_kei

(OO⑧)List という抽象データ型の狙いは、配列による実装を連結リストによる実装に差し替えても問題なく動くコードを書けるようにすること。この例から、抽象データ型においてポリモフィズムは便利ではあるけれど必須ではないことがわかる。差替えのためにはコードを書き換えることも可能だから。

2020-02-22 20:54:02
杉本啓 @sugimoto_kei

(OO⑨)一方で、メッセージ・パッシングのオブジェクト指向ではどうか。受け手が何をするかは受け手次第、という世界を実現するために、ポリモフィズムは必須だ。 ポリモフィズムが無ければ、Observer パタンも Command パタンも Visitor パタンも使えなくなる。

2020-02-22 20:54:43
杉本啓 @sugimoto_kei

(OO⑩)じっさい、ポリモフィズムがなければ GoF のパタンのかなりの部分が壊滅する。これらのパタンは、抽象データ型の枠組みに立脚するものではない。むしろ、メッセージ・パッシングのオブジェクト指向に由来している。

2020-02-22 20:56:07
杉本啓 @sugimoto_kei

(OO⑪)以上、抽象データ型のオブジェクト指向とメッセージ・パッシングのオブジェクト指向の違いを、①メッセージの送り手と受け手の関係性、②ポリモフィズムに対する態度、という視点から説明してみた。こうした見方は分かりやすいのではないだろうか。

2020-02-22 20:56:57
杉本啓 @sugimoto_kei

(OO⑫)そして付け加えるならば、この2つの違いは、両者の狙いの違いに依拠する。抽象データ型のオブジェクト指向の狙いはひとことで言えば「情報隠蔽」だ。オブジェクトの利用側に、知らなくて済む詳細を開示しないことだ。

2020-02-22 20:57:38
杉本啓 @sugimoto_kei

(OO⑬)これに対して、メッセージ・パッシングのオブジェクト指向の狙いは、全体を構成する各部分が実行時に結合され、その結合のされ方も、ユーザーの振る舞いに応じてダイナミックに変わっていくような、ソフトウェア構造を作り出すことだろう。

2020-02-22 20:58:34
杉本啓 @sugimoto_kei

(OO⑭)僕は実務家であって、抽象データ型もメッセージ・パッシングもそれほど深く研究しているわけではない。間違い・誤解があると思うが、シロウトなりにひとつの理解を紹介するのも意味はあるかと思って書いてみました。批判/反論、大歓迎です。

2020-02-22 20:59:22
極端流形式仕様 初代𝕍𝕚𝕖𝕟𝕟𝕒𝕋𝕒𝕝𝕜𝕖𝕣 @tomooda

@sugimoto_kei 機構上の違いでいうと、メッセージングなオブジェクトへのメッセージ送信では、メッセージ名は実行時にオブジェクトに届けられてから解決します。抽象データ型のオブジェクト指向のうち、「クラス型のメソッドを呼び出す」時にはメソッド名はコンパイル時に解決されてvtableインデックスになります。

2020-02-22 21:16:41
極端流形式仕様 初代𝕍𝕚𝕖𝕟𝕟𝕒𝕋𝕒𝕝𝕜𝕖𝕣 @tomooda

@sugimoto_kei 「インターフェース型のメソッドを呼び出す」時にはメソッド名が実行時に解決されますが、解決可能であることがコンパイル時に確定しています。メッセージの場合は確定していません。(デフォルトハンドラを含めれば、いつでも解決可能ですが

2020-02-22 21:18:44
杉本啓 @sugimoto_kei

どのメッセージに応えるかは、実行時に、受け手側が、メッセージを受けてから決定できるという点は、確かに触れておくべきでしたね。 RoR なんてまさにそれで成立しているわけだし、プログラミング(というかメタプログラミング)の可能性を大きく広げる。

2020-02-22 21:31:40
極端流形式仕様 初代𝕍𝕚𝕖𝕟𝕟𝕒𝕋𝕒𝕝𝕜𝕖𝕣 @tomooda

@sugimoto_kei というのが現状の技術的な違いですが、将来的にはもっと違いが広がるだろうと期待しています。メッセージングの場合には、Scratchのようにレシーバが特定されない場合もあるわけですし、他にも色々な新しい形態のメッセージングが発明されるだろうし、その暁にはSmalltalkにトドメを刺せます。

2020-02-22 21:22:02