オブジェクト指向とは?

オブジェクト指向の歴史

英語では「object-oriented」で、1960~1980年代のプログラミング手法から始まり、その応用としてソフトウエアの設計・分析の手法、近年はユーザーインターフェース・エクスペリエンスのデザイン、オブジェクト指向存在論なる哲学分野にまで、広く使われる用語です。

オブジェクト指向の「オブジェクト」は、1967年に発表されたSimula 67というプログラミング言語に組み込まれた当時としては新しい同名の言語機能(あるいはそれに準ずる概念)を指し、それは端的に自らに関連した操作を記述した関数(もしくはプロシージャ。総じて「手続き」)を自分の中に持っている特殊なデータを表します。またSimula 67には、このオブジェクトの仕様の定義と実体化(インスタンス化)のための「クラス」という言語機能があり、これは既存のクラスを継承し差分を書き足すだけで類似の新しいクラスを定義できる機構を備えていました。

このSimula 67の「オブジェクト」と「クラス」という2つの言語機能やその振る舞いをヒントにしたり応用することで、次の2つのアイデアが提案されました。

オブジェクト指向の考え方 5th Edition (top gear) [ Matt Weisfeld ]

①「メッセージング(メッセージ送信)による決定の遅延の徹底」…アラン・ケイは、オブジェクトを生物の細胞やインターネット(当時はその前身のARPAネット)を構成するコンピューターに見立て、それらが互いにメッセージを送りあうメタファー(あるいは実際に送るのでもよい)でプログラムを書いたり動かしたりすることで、堅牢で変化に柔軟に対応できる長寿命のソフトウエアを構築できないかと考え、Smalltalkという言語処理系でその有効性を検証しました 。

②「クラスによる抽象データ型の実現(カプセル化・継承・多態性)」…ビャーネ・ストラウストラップは、Algolへのクラス(とオブジェクト)の拡張であるSimula 67を踏襲し、Cに対しても同じようにクラスを追加することで、C with Classesを経てC++を設計しました。この過程で彼は、クラスをユーザー定義のデータ型(広い意味でのバーバラ・リスコフの抽象データ型[5] )と見做すことが可能であることに気がつき、クラスの継承により、部分型を定義したり、静的型チェックによる安全なプログラミングが可能であると考えました 。なおこのアイデアについては、クラスの発案者であるSimula 67の設計者たちや抽象データ型の発案者であるリスコフ(ただし自ら設計のCLUはパフォーマンス優先でクラスは用いずに抽象データ型を実現している)、Eiffelの設計者であるバートランド・メイヤーら、複数のグループが時を前後して同様の“気づき”におそらくは自力で到達しています(ここでは知名度とそれに伴う他言語への影響の大きさを鑑み、C++のビャーネ・ストラウストラップを代表格として選びました。あしからず)。

①も②も同じように「オブジェクト指向プログラミング」を名乗ったため、OOPというコンセプトは現在に至るまで混乱を極めています。これは私見ですが、もし、①が最初にオブジェクト指向などと名乗らず「メッセージ指向」と、and/or 続く②が「クラス指向」等々と名乗ってくれていたならば、今日のような混乱や「どちらが真のオブジェクト指向か?」などという不毛な論争の多くは避けられていたはずです。

ともあれOOPは今、特に前置きや断りもなく現れて文脈によって①なのか②なのかを聞き手・読み手側が判断しなければならなかったり、話し手・書き手の理解不足により両者の混同があったり、はたまた両者が相反しない範囲(例えば、①は可能な限りの遅延結合、②は比較的早期の結合を是とする点で相容れないので、そこはあまり突き詰めない立ち位置)で互いの要素を取り入れた混成として扱われることが多く、実に学習者泣かせの難解な用語となってしまっています。

カプセル化と継承

  • Smalltalkのごく初期の実装では、クラスは継承機構を持たず、メソッドも独立した関数ではなく、非同期ではないながらもコンセプトに従い、実際にオブジェクトにメッセージを送る機構を採用していました。しかし速度面の問題などから、その後のSmalltalk-76[12] 以降の実装で はSimula スタイルのクラス(つまり、継承機構を有し、メソッドを独立した関数としてクラスに内包する)を採用して、メソッド(つまりメンバー関数)の動的呼び出しをもってメッセージ・パッシングと称する省コスト版(呼び出すメソッドが見つからない時だけメッセージはハンドリングできる)の機構に置き換えられました。

    以来このため①と②それぞれが目指すところを知らずに、例えばSmalltalkとC++とで比較して単に動的型か静的型かといった程度の違いしか見分けられず、しょせんは同じOOP向け言語だろう…といった誤解が生じやすくなってしまった経緯も混乱に拍車をかけてしまっています。加えて、Simula 67スタイルのクラスを採用したことで、Smalltalkは本来の目的である①に反しない範囲で(あるいはそれを敢えて放棄することで)極めて限定的ながらも②のOOPもサポート可能になったことにも注意を払う必要があるでしょう。

  • ①の実践の場であるSmalltalkに対して批判的に派生して考案されたのが「プロトタイプベースのオブジェクト指向」です。当初はメッセージングを重視していましたが、シンプリシティを追求するうちにメッセージングというメタファーすら無用と排除され、オブジェクトに相当する「フレーム」と、それに値(関数を含む)の格納場所に相当する「スロット」(存在しないスロットに対するアクセスをプロトタイプ等別のフレームに委譲するための特殊なスロットを含む)だけがあればすべては事足りるという、①からはほぼ独立したアイデアやそれを基にしたスタイルとして認知されています。
  • メッセージといえばカール・ヒューイットのアクター理論を思い浮かべる人が多いかと思いますが、こちらは、アラン・ケイらのSmalltalk-72のメッセージングによるコンピューティングをヒントに、並行・並列の非同期処理にかかわる問題の解決に役立てようと考案され定式化されたものです。なおヒューイットは、彼が影響をうけたSmalltalk-72と、彼のPLANNERに影響をうけて一部仕様のみ策定され実装には至らなかった別言語のSmalltalkとを混同しているため、彼によるアクターとSmalltalkの関係についての言及やそれに基づく記述は注意深く読み解く必要があります。
  • Erlangのメッセージングはヒューイットの考えるアクターの要件を満たしておらず 、また、Smalltalkで実践されたケイのメッセージングのアイデアとは無関係に成立したもののようです(少なくとも論文では両者への言及は無いようなので…)。ところが同言語の設計者であるジョー・アームストロングは晩年、①の真の担い手がErlangであるかのように受け取れる発言[20] をしていて大変興味深いです。
  • ②の三要素は、カプセル化=抽象データ型の特徴、継承=クラスの特徴、多態性(ポリモーフィズム)=主に継承(≒クラスを使いこなすこと)により部分型多相が可能になること、つまり②の本質である「クラスによる抽象データ型の実現」を端的に表します。
  • ②の継承については、Eiffelなど一部の実装ではクラスをデータ型として、それを継承した派生クラスを部分型として扱うことに問題が生じることが比較的早い時期に指摘されていて、クラスやその継承でではなく新たに考案された言語機能としてのインターフェースを用いることが定着しています。
  • 抽象データ型というのは、組み込み型の「具象」に対する「抽象」という意味で、前述の通り簡単には「ユーザー定義のデータ型」と言い換えられます。実装面では、データと手続きをセットにして、データの内部情報はそのセットにした手続きでしか変更できないようにする機構(カプセル化、あるいは情報隠蔽・アクセスコントロール)を「型」という視点で管理するアイデアです。クラスが提供する機能と区別がつきにくい(②がどんなアイデアだったかを思い起こせば、ある意味当然…)ですが、Simula 67に立ち返りそもそも同言語のクラスは当初、カプセル化のしくみを欠いていた(つまりクラスは元々は抽象データ型の要件を満たすべく考案されたものではない)ことや、また、抽象データ型はデータと手続きをセットにはするが、手続きを型に内包する必要はかならずしもないこと(例:CLUのクラスター。狭義、あるいは言語機能としての「抽象データ型」)などを知ると両者の区別がつきやすくなるかと思います。
  • 抽象データ型や部分型多相をクラス(や、その機能である継承)を使って実現するアイデアが②のOOPなので、「抽象データ型やポリモーフィズムはOOP以外でもできる」とか「それらはOOPには必須ではない」という指摘は本末を転倒しています。

オブジェクト指向でなぜつくるのか 第3版 知っておきたいOOP、設計、アジャイル開発の基礎知識 [ 平澤 章 ]

最新情報をチェックしよう!
>プログラミング 独学

プログラミング 独学

本当にプログラミングを学びたい人のためになるブログにしたいと思っていますので、些細なことでも気が付いたのであればご報告いただけると幸いです。

CTR IMG