オブジェクト指向プログラミング

出典: フリー百科事典『ウィキペディア(Wikipedia)』
ナビゲーションに移動 検索に移動

オブジェクト指向プログラミング(オブジェクトしこうプログラミング、: object-oriented programming、略語:OOP)とは「オブジェクト」という概念に基づいたプログラミングパラダイムの一つである。 オブジェクトは、任意個数のフィールド 属性プロパティまたは変数)で構成されるデータと、任意個数の(メソッドまたは関数)で構成されるコードのひとまとまりで構成される。

オブジェクトの特徴として、オブジェクト自身の手続きが自身のデータフィールドを読み書きできることが挙げられる(オブジェクトにはthisselfという概念がある)。また、OOPでは、相互に作用するオブジェクトを組み合わせてプログラムを設計する[1][2]。OOP言語のありかたは多様であるが、最も一般的といえるものは、オブジェクトがクラスのインスタンスであり、また、オブジェクトのクラスとして規定されるクラスベースといわれるものである。

広く使われているプログラミング言語の多く(C++、Java、Pythonなど)は、マルチパラダイムであるが、程度の差はあれ、オブジェクト指向プログラミングをサポートしており、大抵は命令型手続き型プログラミングとの組み合わせで用いられる。 主なオブジェクト指向言語には次のようなものが挙げられる: JavaC++C#PythonRPHPVisual_Basic_.NETJavaScriptRubyPerlSIMSCRIPT(英語版)Object PascalObjective-CDartSwiftScalaKotlinCommon LispMATLAB、そしてSmalltalk


歴史[編集]

UMLによるクラスの表記法。このButtonクラスは、データを表す変数関数を持ち、継承によりButtonクラスのサブセットとしてサブクラスを作成することが可能である。また、オブジェクトはクラスのインスタンスである。

現在のオブジェクト指向プログラミングという文脈における「オブジェクト」や「指向」を表す用語が初めて登場したのは、1950年代後半から1960年代前半にかけてのマサチューセッツ工科大学(MIT)においてである。 1960年代初頭の人工知能グループ界隈では、「オブジェクト」はプロパティ(属性)を持つ個体識別可能なアイテム(LISPのatom)を意味していた[3][4]。 後にアラン・ケイは、1966年にLISPの内部構造を詳細に理解したことが彼の考え方に強い影響を与えたと述べている。[5]

私は、オブジェクトとは、生物の細胞やネットワーク上の個々のコンピュータのようもの、そしてそれらのコミュニケーションは専らメッセージによって行なわれるもの、と考えていました(つまり、メッセージングは最初から存在していたのですが、プログラミング言語でメッセージングを実用的かつ効率的に行う方法を見つけるまでには時間がかかりました)。
アラン・ケイ, [5]

MITにおける初期の例としては、この他にも、1960年から1961年にかけてアイバン・サザランドが作成したSketchpadが挙げられる。サザランドは、1963年の技術レポートの用語集(Sketchpadに関する自身の博士論文をもとにしたもの)で、グラフィカルなインタラクションに特化しているとはいえ「オブジェクト」と「インスタンス」の概念を定義している(クラスの概念は"master"または"definition"として把握されている)。[6] また、MIT版のALGOLであるAED-0では、データ構造(この言語の方言では"plexes"と呼称)と手続きを直接結びつけ、後に「メッセージ」、「メソッド」、「メンバ関数」と呼ばれるようなものの萌芽がみられる。[7][8]


1962年、クリステン・ニゴールノルウェー計算センターでシミュレーション言語のプロジェクトを開始した。これは彼が以前に用いたモンテカルロ法と実世界のシステムを概念化する仕事に基づくものであった。オーレ=ヨハン・ダールが正式にプロジェクトに参加し、UNIVAC I(UNIVAC 1107)上で動作するSimulaプログラミング言語が設計された。Simulaは、クラスオブジェクト、継承、ダイナミックバインディングなど、今日のオブジェクト指向プログラミングには不可欠である重要な概念を導入した。[9] Simulaはまた、プログラミングにおけるデータ保全を考慮して設計されたものでもあった。プログラミングのデータ保全のために参照カウントによる検出プロセスが実装されたのに加え、最終手段としてガベージコレクタメモリ内の使用されていないオブジェクトを削除するようになっていた。しかし、データオブジェクトの概念は1965年には既に確立されていたものの、プライベート(-)やパブリック(+)といった変数スコープのレベルによるデータのカプセル化については、アクセスする手続きもまた隠蔽できなければならなかったため、Simulaでは実装されなかった。[10]

初期の段階では、Simulaはプログラミング言語ALGOL 60のための手続きパッケージとされていた。しかし、ALGOLによる制約に不満を感じた研究者たちは、UNIVAC ALGOL 60コンパイラを使用した本格的なプログラミング言語としてSimulaを開発することにした。ダールとニゴールは1965年から1966年にかけてSimulaの普及に尽力し、スウェーデン、ドイツ、ソビエト連邦などでSimulaの使用が増加した。1968年には、バロース B5000上で広く利用されるようになり、後にはURAL-16コンピュータ上にも実装された。1966年、ダールとニゴールはSimulaのコンパイラを書いた。彼らは、SIMSCRIPT英語版(自由形式の英語的な汎用シミュレーション言語)を実装に用いて、アントニー・ホーアのレコード・クラス概念を取り入れることに熱心に取り組んだが、彼らは、一般化されたプロセスの概念として、レコード・クラスの属性を保持する層と、接頭辞(prefix)の系列を保持する層の二層構造とする方式に辿り着いた。 接頭辞の系列を通じて、プロセスは先行する定義を参照し、それらの属性を追加することができる。このようにしてSimulaは、クラスとサブクラスの階層を導入し、これらのクラスからオブジェクトを生成することを可能にする方法を導入することとなった。[11]

1972年にはIBM System/360およびIBM System/370IBMメインフレーム用にSimula 67コンパイラが完成[9]。同年、フランスのCII 10070およびCII Iris 80メインフレーム用のSimula 67コンパイラが無償で提供された。1974年には、Simulaユーザー会は23カ国のメンバーを有するまでになっていた。1975年初頭、DECsystem-10メインフレームファミリー用のSimula 67コンパイラが無償でリリースされ、同年8月までにDECsystem-10のSimula 67コンパイラは28サイトにインストールされた(そのうちの22サイトは北米)。オブジェクト指向のプログラミング言語としてSimulaは、貨物港における船舶と積載貨物の動きを調査・改善するための研究のような、物理モデリング研究に携わる研究者に主に利用されていた[9]

1970年代、Xerox パロアルト研究所(PARC)において、アラン・ケイダン・インガルスアデル・ゴールドバーグらによって、プログラミング言語Smalltalkの最初のバージョンが開発された。Smaltalk-72はプログラミング環境を含み、動的型付けであり、当初はコンパイルしてからの実行ではなくインタプリタ実行であった。Smalltalkは、言語レベルでのオブジェクト指向の適用と、グラフィカルな開発環境で注目されたが、Smalltalkが様々なバージョンを経て成長するにつれ、この言語への関心も高まっていった[12]。 SmalltalkはSimula 67で導入されたアイデアの影響を受けてはいるものの、クラスを動的に生成・変更できるなど、完全に動的なシステムとして設計された[13]

1970年代、SmalltalkはLispコミュニティに影響を与え、Lispコミュニティは、Lispマシンを通じて開発者に紹介されたオブジェクトベースの技術を取り入れた。Lispの様々な拡張機能(LOOPSやFlavorsなどが導入した多重継承Mixin)の試みは、最終的に関数型プログラミングとオブジェクト指向プログラミングを統合し、メタオブジェクト・プロトコルによる拡張を可能にしたCommon Lispのオブジェクト指向システムへとつながった。 1980年代には、メモリ上のオブジェクトをハードウェアでサポートするプロセッサ・アーキテクチャを設計する試みがいくつか行われたが、Intel iAPX 432Linn SmartRekursivなど、いずれも商業的に成功しなかった。

オブジェクト指向という言葉自体は、計算機科学者アラン・ケイによって作り出されている。Simula言語などにインスパイアされたケイが1967年頃に口にしたと伝えられるこの造語は[14]、彼が1972年から開発を始めた言語Smalltalkの設計を説明する過程で明確な用語として発信され、1981年頃から知名度を得るようになった。80年代半ばになるとオブジェクト指向の解釈は、元々のアラン・ケイによるSmalltalkの様式と、1983年に計算機科学者ビャーネ・ストロヴストルップが公開したC++の様式に二分された。前者ではメッセージングという概念が基礎にされ、後者ではSimula67由来の諸機能を加えた抽象データ型のスーパーセットが基礎にされていた。

1980年のSmalltalk-80は、元々はメッセージを重視していたケイを自嘲させるほど同期的で双方向的で手続き的なオブジェクト指向へと変貌していた。それでも動的ディスパッチと委譲でオブジェクトを連携させるスタイルは画期的であり、1994年に発表されるデザインパターンの模範にもされている。1981年に当時の著名なマイコン専門誌『BYTE』が、Smalltalkとその理念であるオブジェクト指向を紹介して世間の注目を集める契機になったが、ケイの思惑に反して技術的関心を集めたのはクラスの仕組みの方であった。オブジェクト指向は知名度を得るのと同時に、Simula発のクラス継承と動的ディスパッチ)および抽象データ型(データ抽象とデータ隠蔽)にマウントされて解釈されるようになり、それらのコンセプトがケイの構想とは無関係であったことから、オブジェクト指向の定義はケイの手を離れて独り歩きするようになった。


Simulaを研究対象にしていたAT&Tベル研究所の計算機科学者ビャーネ・ストロヴストルップは、1979年からクラス付きC言語の制作に取り組み、1983年に「C++」を公開した。C++で実装されたクラスは、Simula由来の継承と仮想関数に加えて、段階的なレキシカルスコープの概念をクラス構造に応用したアクセスコントロールを備えていた。C++で確立されたアクセスコントロールは情報隠蔽によるデータ抽象を提示したが、コードスタイル上ほとんどザル化されており、その理由からストロヴストルップ自身もC++は正しくない(not just)オブジェクト指向言語であると明言している。1986年にソフトウェア技術者バートランド・メイヤーが制作した「Eiffel」の方は、正しいオブジェクト指向を標榜してクラスのデータ抽象を遵守させるコードスタイルが導入されていた。クラスメンバ(フィーチャー)は属性/手続き/関数の三種構成で、手続きで属性を変更して関数で属性を閲覧するという形式に限定されており、これは抽象データ型に忠実な実装であった。アクセスコントロールはC++のとは異なるクラス指名方式にされ、仮想関数機能は延期手続き/関数として実装された。


1986年からACMOOPSLAを年度開催するようになり、オブジェクト指向は従来の構造化開発に代わる技術として明確に意識され始めた。OOPSLAのプログラミング言語セクションでは、抽象データ型を基礎にしたクラス・パラダイムが主要テーマにされ、それを標準化するための数々のトピックが議題に上げられている。モジュール分割抽象化再利用性階層構造、複合構成、情報隠蔽、実行時多態、動的束縛総称型永続性並行性自動メモリ管理といったものがそうであり、参画した識者たちによる寄稿、出版、講演を通して世間にも広められた。そうした潮流の中でストロヴストルップはデータ抽象の重要性を訴え、リスコフ基底と派生に分けたデータ抽象の階層構造の連結関係(置換原則)について提言した。契約による設計開放閉鎖原則を提唱するメイヤーが1988年に刊行した『オブジェクト指向ソフトウェア構築』によるEiffel式のクラス理論は高く評価され、Eiffelを現行の模範形とする声も多く上がった。ただしこれは学術寄りの意見でもあったようで、世間のプログラマの間では厳格なEiffelよりも、柔軟で融通の利くC++の人気の方が高まっていた。他方でアラン・ケイのメッセージ・メタファに忠実であろうとする動きもあり、1984年に制作された「Objective-C」はC言語をSmalltalk方向に拡張してメッセージ式を平易化した言語であった。1987年にパロアルト研究所で誕生した「Self」は、Smalltalkのクラスベース設計をより柔軟に平易化したプロトタイプベースを編み出している。


ネットワーク技術の発展に連れて、データとメソッドの複合体であるオブジェクトの概念は、分散システム構築のための基礎要素としての適性を特に見出される事になり、IBM社Apple社サン社などが1989年に共同設立したOMGは、企業システムネットワーク向け分散オブジェクトプログラミング規格となるCORBAを1991年に発表した。その前年にマイクロソフト社ウェブアプリケーション向けの分散オブジェクトプログラミング技術となるOLEを発表し、1993年にはCOMと称するソフトウェアコンポーネント仕様へと整備した。このCOMの利用を眼目にしてリリースされた「Visual C++」「Visual Basic」はウェブ時代の新しいプログラミング様式を普及させる先駆になった。この頃にデータ抽象、データ隠蔽、アクセスコントロールおよびインターフェースによるプログラムの抽象化は、総じてカプセル化の概念でまとめられるようになった。クラスの継承が最もオブジェクト指向らしい機能と見なされていたのが当時の特徴であった。継承構造を利用した振る舞いサブタイピング及び動的ディスパッチは多態性という用語に包括された。こうしていわゆるオブジェクト指向の三大要素がやや漠然と確立されている。1996年にサン社がリリースした「Java」は三大要素が強く意識されたクラスベースであり、その中の分散オブジェクト技術はBeansと呼ばれた。類似の技術としてApple社もMacOS上でObjective-Cなどから扱えるCocoaを開発している。また、1994年から96年にかけて「Python」「Ruby」「JavaScript」といったオブジェクト指向スクリプト言語がリリースされ、従来の静的型付けに対する動的型付けと、クラスベースに対する新しいプロトタイプベースの認知度を高めている。


抽象化を旨とするオブジェクト指向ではそのプログラミング自体の抽象化も積極的に推進されている。80年代後半から立ち上げられたオブジェクト指向分析(OOA)やオブジェクト指向設計(OOD)の各手法から導き出される概念モデルを、多角的にチャート化ないしダイアグラム化するための数々のオブジェクト指向開発方法論がOOPSLA界隈の識者たちから発表されるようになり、そこで用いられる形式言語オブジェクトモデリング言語英語版と呼ばれた。これはプログラミングのためのプロトタイプ(ひな型)として重視され、オブジェクト指向ではモデリング言語プログラミング言語が並んでソフトウェア開発の両輪になった。1994年にモデリング言語によるGOFデザインパターンが初回発表され、これはオブジェクト指向教育で非常に重視されるようになった。1995年にモデリング言語の標準化を企図したUMLOOPSLAで初回発表され、1997年にOMGの標準モデリング言語として採用された。同年にデザインパターンを帰納的に分析して九原則にまとめたGRASPが発表されている。

特徴[編集]

OOPではクラスベースと呼ばれるスタイルが多数派である。他にプロトタイプベースと呼ばれる後発のスタイルもあるが、こちらは少数派である。クラスベースのOOP言語は、Smalltalk様式とC++様式で二分されており[要出典]、C++様式の方がずっと多数派である。C++様式は、静的型付け動的型付けの分類で大別されている。それらの主な特徴を箇条書きするとこうなる。

  • クラスベース - クラスのインスタンス化でオブジェクトを構築する。
    • Smalltalk様式 - クラスとインスタンスの相対性を付与してオブジェクトを体系化している。動的型付け中心。メッセージパッシングによる多態性。
    • C++様式 - クラス(型)とインスタンス(値)に分離してオブジェクトを体系化している。動的ディスパッチ英語版による多態性。
      • 静的型付け - オブジェクトの構成解釈(型チェックなど)を主にコンパイル時にする。
      • 動的型付け - オブジェクトの構成解釈(型チェックなど)を主に実行時にする。
  • プロトタイプベース - オブジェクトのクローンでオブジェクトを構築する。クラスとインスタンスの相対性をオブジェクトから撤廃して、プロトタイプでオブジェクトを体系化している。動的型付け中心。動的バインディングによる多態性。

なお、場合によっては C言語などオブジェクト指向を支援しない言語でOOP的なプログラミングが行われることもある。

クラスとインスタンス[編集]

OOPの要点であるクラスは、データ構造とそれを扱うための操作・振る舞いをひとまとめにした一種のプログラムモジュール機能として定義されており、その実装はSimula67由来の継承と動的ディスパッチを加えた抽象データ型のスーパーセットにされていることが多い。クラスのデータ構造はレコード型構造体に似た書式で定義されることが多く、データ構造の要素は言語ごとにフィールドプロパティ属性、メンバ変数などと呼ばれている。クラスに定義される操作・振る舞いはメソッドやメンバ関数などと呼ばれる。[要説明]

OOP言語のクラスと、そうでない言語でのモジュールの違いを知ることは、OOPを理解する上でも重要になる。どちらも手続きデータの複合体であるが、クラスの第一の特徴はそれに継承が備えられていることであり、次にThis参照の機構と、継承構造上の内包的な動的ディスパッチ英語版である。その次になる情報隠蔽英語版と、定義と実装に分離しての抽象化の機構は、OOP以前のモジュラルプログラミング英語版からのものである。振る舞い抽象を担っているインターフェースの概念もそちらが先例であったが、データ抽象を担っているカプセル化(情報隠蔽とThis参照の融合)の採用はOOPが最初である。継承構造上の内包的な動的ディスパッチによるサブタイピング(=ポリモーフィズム)はOOP発祥であるが、それを純粋化すると前述のインターフェースになる。OOP以前の構造化開発のモジュールには情報隠蔽はあるが、継承はなく、カプセル化ポリモーフィズムといった抽象化の諸機構も持たない。なお、振る舞いサブタイピング英語版多重ディスパッチのOOPでは軽視されており、カプセル化は動的型付けのOOPではしばしば軽視されている。

C++様式のクラスベースはオブジェクトを、型理論に沿った[要出典] (type)と値(term)に分離している。その型の一種であるユーザー定義型(user defined type)がクラスにされており、クラスで型付けされた値がインスタンスになっている。ユーザー定義型とは構造体に似たデータ複合体であり[疑問点]、OOPでは手続き(のポインタ)もそのメンバにされている。クラスはインスタンスのひな型であり、インスタンスはクラスを実体化したものである。実体化=インスタンス化である。コンパイル時に型チェックされるユーザー定義型は静的型付けであり、実行時に型チェックされるユーザー定義型は動的型付けである。なお、Smalltalk様式のクラスベースは型理論依存型に似ている。依存型は型と値の境界がない型付けである。

オブジェクトとは[編集]

クラスベース言語での「オブジェクト」は、インスタンスを指す用語として説明されているが、このような重複語になった背景にはOOP原点のSmalltalkの設計がある。Smalltalkは、全てのプログラム要素はオブジェクトであり、全てのオブジェクトはクラスのインスタンス化であり、クラスもまたオブジェクトであり、オブジェクトは他のオブジェクトと相互作用(interaction)すると定義していた。そこではクラスもまたメタクラス(型)のインスタンス化(値)になり、そのメタクラスもまた他のメタクラスのインスタンス化になっていたので、クラスインスタンスは即ちオブジェクトの性質(相対性)を指すための言葉になっていた。これがC++様式では簡素化されて、クラスとインスタンスはの役割に固定され、メタクラスはリフレクション機能に固定されたので、クラスとインスタンス化の相互再帰が失われたオブジェクトは、相互作用できるインスタンスを指しているままで放置された。相互作用とは各種演算と同義であり、Smalltalkのクラスは相互作用できる値でもあるのでオブジェクトであるが、C++様式のクラスはただの型なので演算対象に出来ないことからオブジェクトではなくなっている。

Smalltalk方言のSelfを原点とするプロトタイプベースは、オブジェクトからクラスとインスタンスの相対性を無くしたスタイルである。数値・文字列・配列・関数・シンボル・構造体オブジェクト型)といった基本的な型は備えられているが、これはオブジェクト種類の区別に特化されたものなので、型理論に沿ったクラスベースのそれとは厳密には異なっている。クラス性質を除去したオブジェクトは事実上のインスタンスに一元化されており、その全てが相互作用(interaction)する。オブジェクトの表現はスロット(シンボルとコンテンツのペアデータ)の可変長配列でなされており、オブジェクトの識別は専らダックタイピングによってなされる。クラス概念が無いのでサブクラス化とインスタンス化は成立せず、代わりにクローン(複製)によってオブジェクトの継承がなされており、クローンはインスタンス化の代替になる。複製元オブジェクトは、複製先オブジェクトのプロトタイプと呼ばれる。

カプセル化[編集]

データ構造とそれを扱うためのメソッド群を情報隠蔽の概念と合わせてモジュール化(パッケージ化)するという手法がカプセル化と呼ばれる。カプセル化されたメソッドは、This値が暗黙の先頭引数として常に渡されるように実装される。This値とはクラスのデータ構造をメモリ展開するためのヒープ領域の基底アドレスを指しており、インスタンス化時に確定されたThis値によってメソッドは専用のデータ構造にアクセスできる。専用メソッドを通してのデータ構造の閲覧と変更は、抽象データ型の考え方に沿ったデータ構造の抽象化を意味することになり、これはデータ抽象英語版と呼ばれる。データ閲覧用メソッドはゲッター/アクセッサと呼ばれ、データ変更用メソッドはセッター/ミューテイタと呼ばれる。

情報隠蔽英語版とはそのクラスのデータ構造の各要素および各メソッドを必要に応じて内部隠蔽するという概念である。内部隠蔽されたデータ要素とメソッドはそのクラス外部からのアクセスが禁止される。抽象データ型本来の形式ではデータ構造のみが隠蔽対象になるので、これはデータ隠蔽とも呼ばれる。隠蔽指定外のデータ要素とメソッドは外部公開されて、そのクラス外部からもアクセス可能になる。外部公開の範囲を指定する機能はアクセスコントロールと呼ばれており、これが内部隠蔽の仕組みを担っている。クラスのレキシカルスコープを基準にした段階的なアクセス許可範囲は可視性と呼ばれる。可視性は無制限・任意クラスグループ限定・派生クラスグループ限定・自クラス限定(内部隠蔽)の四段階がUMLクラス図では標準にされている。

継承[編集]

既存クラスのデータ/メソッド構成に、任意のデータ/メソッド構成を付け足して、既存構成+新規構成の新しいクラスを定義するという手法が継承と呼ばれる。また、各クラスの共通構成パートを括りだして特有構成パートと分離することでオブジェクトを分類体系化し、同時にその共通構成パートの記号化によってソースコード内の重複記述を削減する機能とも解釈される。これは差分プログラミング目的の継承であり、実装継承(implementation inheritance)とも呼ばれた。

リスコフ置換原則開放/閉鎖原則が取り上げられると、既存構成に抽象メソッドを置いて新規構成にその実装メソッドを置くというメソッドオーバーライドを用いるための振る舞いサブタイピング英語版目的の継承の方が重視されるようになり、これは界面継承(interface inheritance)とも呼ばれた。メソッド定義の引き継ぎとサブタイピングを中心にしたIs-a関係主体の継承をUMLクラス図は特化(specialization)と定義している。

既存クラスはスーパークラス・親クラス・基底クラスなどと呼ばれ、新しいクラスはサブクラス・子クラス・派生クラスなどと呼ばれる。親と子は差分プログラミング重視で、基底と派生はサブタイピング重視で用いられる。継承できるクラスが一つに限られている単一継承を採用している言語と、継承できるクラスの数に制限がない多重継承を採用している言語がある。抽象メソッドを持つクラスは抽象クラスと呼ばれる。基底クラス側でリターン型とパラメータのみが定義されて実行コードブロックが未定義のままの抽象メソッドは、その派生クラス側の実装メソッドでオーバーライドされる。オーバーライドは遅延結合による多相な複雑系アルゴリズムを表現するオープン再帰(open recursion)のメカニズムにもなっている。

抽象メソッドのみで構成される純粋抽象クラスはインターフェースと呼ばれ、その継承をUMLクラス図は実装(implementation)と定義している。インターフェースの実装は、サブタイピングIs-a関係を完全順守させるメカニズムである。また、クラスへの機能注入を目的にして、主に具象メソッド群をクラスに継承させるというアプローチもあり、これはミックスイン(mix-in)と呼ばれる。mix-inのメソッド集合体は、トレイトの形態にされることが多い。mix-inはUMLクラス図では扱われていない継承関係である。

ポリモーフィズム[編集]

異なる種類のクラスに共通の操作インターフェースを持たせてオブジェクトの振る舞いを抽象化するという手法がポリモーフィズム(多態性)と呼ばれる。OOPで語られる多態性はもっぱら継承構造を利用したサブタイプ多相英語版を対象にしているが、アドホック多相英語版もサポート的に用いられており、パラメトリック多相英語版はコンポジションで用いられている。そのサブタイプ多相の設計としては、コンパイル時に確定されたメソッド名から呼び出されるプロセス内容が実行時に決定されるという仕組みを指しており、一つのメソッド名からその実行時状態に合わせた個別のメソッド処理が呼び出されるようにするという演繹的意味と、各クラスの同種機能メソッドを一つの共通メソッドにまとめて実行時状態に合わせたメソッド処理が呼び出されるようにするという帰納的意味がある。

その実装としてはメソッドオーバーライド機能を活用した仮想関数と、実行時パターンマッチング機能を活用した総称関数の二つが挙げられる。仮想関数英語版はスーパークラスの抽象メソッドの呼び出しを、それをオーバーライドしたサブクラスの実体メソッドの呼び出しにつなげるという動的ディスパッチ機能である。総称関数英語版はオブジェクトの実行時パターンマッチングを使用する独立関数であり、その引数にされた各オブジェクトの型(=クラス)の組み合わせに従って実行コードブロックを選択決定するという多重ディスパッチ機能である。同名アルゴリズムを個々の派生クラスのメンバ関数に分散記述するのが仮想関数であり、個々の派生クラスの同名アルゴリズムを一つの独立関数に一括記述するのが総称関数である。

コンポジションとデリゲーションとジェネリクス[編集]

コンポジション (合成)英語版デリゲーション(委譲)は、OOPでは継承と対比される機能である。継承(特化)はIs-a関係の暗黙委譲、合成はHas-a関係の明示委譲と読み替えることができる。合成とは、特定処理の委譲先になる部品クラスの1個以上を持たせたクラス構造であり、そのクラスがとある処理を要求されてそれに対応できるデータ/メソッドを持っていない場合は、それに対応できる部品クラスを選択して処理を委譲するという仕組みである。その要求判別と選択過程を自動サーチ化したものが継承であり、部品クラスを基底クラスに置き換えて暗黙の委譲先にしたものである。しかしその自動サーチは、クラス階層に分散配置されているデータ/メソッドのどれが実際にアクセスされるのかという把握を困難にしたので、ここで差分プログラミング用途の継承の欠点が取り沙汰されるようになり、その後のクラスの機能拡張と分類体系化では、継承と合成の使い分けが重視されるようになった。また、Has-a関係はUMLクラス図では合成(composition)と集約(aggregation)に分けられている。

ジェネリクス(総称化)は、オブジェクトのデータ構造を汎用化して、それに汎用アルゴリズムの数々を適用できるようにした技術である。様々なデータ要素を内包するコンポジション(合成)オブジェクトはコンテナ(List/Set/Mapなど)と呼ばれ、その要素の型を型変数化することで汎用的なデータ構造を表現し、その要素の型はコンテナのインスタンス化時に与えられる型パラメータによって決定される。ジェネリクスはデータ構造アルゴリズムを個別化しての柔軟なコンポーネント性を促進させ、反復子の方法論を確立した。また、圏論に見立てられたコンテナおよび対象に見立てられたデータ要素の入れ子構造と、に見立てられたサブタイピングの融合は、共変性と反変性の手法に発展した。

動的ディスパッチとメッセージパッシング[編集]

動的ディスパッチ英語版は、OOPのポリモーフィズムの原型機能であり、コンパイル時に確定されたメソッド名から呼び出されるメソッド内容(実行コードブロック)が、実行時に選択決定(ディスパッチ)される仕組み全般を指している。メソッドに与えられた各引数の型の組み合わせに従って、実行コードブロックが選択決定される仕組みのシングルディスパッチと多重ディスパッチを包括している。先頭引数の型パターンマッチング固定でディスパッチされるのはシングルになり、そうでないならば多重になる。例えば仮想関数Thisのシングルディスパッチである。

メッセージパッシングでは引数の型に加えて、メソッド名も実行時に解釈される要素にされており、そこでただのシンボルとして扱われるメソッド名はセレクタと呼ばれている。セレクタはメッセージ式を基本文とするSmalltalk様式のOOPで用いられる。object selector: paramような書式でオブジェクトの共通窓口になるメッセージレシーバーに、セレクタと引数値で構成されたメッセージが送られる。また、object.call(method_name, param)のような書式でオブジェクトの共通窓口関数をコールするのもメッセージパッシングと呼ばれる。これはRPCORBなどの分散オブジェクト技術で用いられている。メソッド名(関数名)も実行時に解釈されるという特徴を指してメッセージパッシングと呼ぶ。メッセージレシーバーでは、渡されたセレクタのパターンマッチングに従って実行コードブロックがディスパッチされることが多く、OOP原点のSmalltalkは、引数とThisが与えられるその実行コードブロックをメソッドと呼んでいた。

インターフェースとトレイト[編集]

インターフェースは、カプセル化継承サブタイピング用法を促進した機能である。情報隠蔽とデータ抽象とメソッド抽象を合わせて表現する。クラスから見たインターフェースは自身のサービスのモデル化である。OOPのインターフェースは基本的には抽象メソッドのみで構成される抽象型と定義されている。その実装方式は純粋抽象クラスが基本形にされており、インスタンス化はできない継承専用クラスになって多重継承が前提にされている。インターフェースの抽象メソッドは、その実装クラスの同名具象メソッドでオーバーライドされる。インターフェースの各抽象メソッドはセッター・ゲッター・プロセスとして動作し、その実装内容は隠蔽されて実行時ごとに決定される。その代表使用例はソフトウェアコンポーネント間の相互通信媒体である。

OOP原点のSmalltalk処理系由来のトレイトは、クラスへの機能注入を目的にしたメソッドの集合体であり、トレイトの多重継承を扱う作法はミックスインと呼ばれている。トレイトの継承はインクルードともされ、これはUMLクラス図の”特化”と”実装”ではない第三の継承概念になるので、従来の標準OOP路線からは外れていた。後の依存性逆転の原則および依存性の注入デザインパターンでは、Mix-inの作法が注目され、そこでのトレイトの役割を与えたインターフェースの応用設計が扱われている。そのMix-inをUMLクラス図は、特定の機能(サーバーデータベースなど)から”実現”されたインターフェース(依存対象)に向けてオブジェクトが”関連”するという図式にしている。この手法は分散オブジェクト技術の後継としてのDIコンテナで用いられている。

デザインパターン一覧[編集]

継承と振る舞いサブタイピング[編集]

継承Is-a関係を表現して、サブクラスインスタンススーパークラスインスタンスを安全に置換できるという直感は、多くのOOP言語には当てはまっておらず、ミュータブルなオブジェクトを扱っていても同様である。型チェック機構付きのサブタイプ多相は、振る舞いサブタイピング英語版の正当性までを保証しない。一般的に振る舞いサブタイピングは非決定性なので、そのための言語機能の実装は非現実的であり、クラスまたはオブジェクトの継承関係の設計は、プログラマの手によって注意深く行われる必要がある。スーパークラスとサブクラス間の理想的な振る舞いサブタイピングを実現するためのデザインパターンとしてよく知られているのが、リスコフの置換原則である。

GOFデザインパターン[編集]

1994年に”Gang of Four”がその著作で発表した23のデザインパターンは、余りに有名である。

生成のパターン
  • 構造のパターン
  • 振る舞いのパターン
  • 責任駆動設計とデータ駆動設計[編集]

    OOPで提唱された責任駆動設計(RDD)とは、特定の機能を実現する責任およびその機能が共有する情報に基づいて、クラスを定義していくデザインパターンである。責任駆動設計では、振る舞い抽象としてのクラスに焦点を当てており、必然的にインターフェース抽象クラスが多用されることになる。

    OOPにおけるデータ駆動設計とは、保持するデータ構造に基づいて、クラスを定義していくデザインパターンである。データ駆動設計では、データ抽象としてのクラスに焦点を当てており、カプセル化抽象データ型の概念に重きが置かれる。レベッカ・ウーフ‐ブロック英語版によって彼女の責任駆動設計と、従来のデータ駆動設計は対比されるようになっている。


    SOLID、GRASPのガイドライン[編集]

    SOLIDのガイドラインは、プログラミングにおける五つの実践の頭文字をとった語呂合わせであり、マイケル・C・フェザーズ[15]が考案し提唱したものである

    GRASP(General Responsibility Assignment Software Patterns)は、クレーグ・ラーマンが提唱したもう一つガイドラインである。

    公式意味論[編集]

    数々の識者によってOOPで扱われる概念を公式化する試みが行われている。OOP概念の解釈に用いられる代表的なコンセプトは以下の通りである。

    ”オブジェクト”の共通認識的な定義または理論を見つけようとする試みはそれほど成功していない。ルカ・カーデリ英語版らによるA Theory of Objects[16]は、比較的成功している例とされる。

    オブジェクト指向言語一覧[編集]

    ここではクラスベースの記述は省略している。

    • Simula67 1967年 静的
    • Smalltalk 1972年 動的・メッセージ式・純粋系
    • C++ 1983年 静的
    • Objective-C 1984年 静的と動的・メッセージ式
    • Object Pascal 1986年 静的
    • Eiffel 1986年 静的・純粋系
    • Self 1987年 動的・プロトタイプベース・メッセージ式・純粋系
    • Modula-3 1988年 静的
    • Common Lisp(CLOS) 1988年(ANSI規格化は1994年) 動的・多重ディスパッチ・メタオブジェクト
    • Oberon-2 1991年 静的
    • Dylan 1992年 動的・多重ディスパッチ
    • Lua 1993年 動的・プロトタイプベース
    • Python 1994年(ver1.0) 動的
    • Delphi 1995年 静的
    • Ada 1995年からOOP化 静的
    • Perl 1995年からOOP化 動的
    • Ruby 1995年 動的・純粋系
    • Java 1996年(ver1.0) 静的
    • JavaScript 1996年(first released) 動的・プロトタイプベース
    • OCaml 1996年 静的・関数型
    • Squeak 1996年 動的・メッセージ式
    • ECMAScript 1997年 動的・プロトタイプベース
    • C# 2000年 静的と動的
    • Visual Basic.NET 2001年 静的
    • D言語 2001年 静的
    • Io 2002年 動的・プロトタイプベース・メッセージ式・純粋系
    • COBOL 2002年からOOP化 静的
    • FORTRAN 2003年からOOP化 静的
    • R言語 2003年からOOP化 動的・関数型・多重ディスパッチ
    • Scala 2003年 静的・関数型
    • Groovy 2003年 動的
    • PHP 2004年からOOP化 静的と動的
    • F# 2005年 静的・関数型
    • MATLAB 2008年からOOP化 動的・関数型
    • Go 2009年 静的
    • Rust 2010年 静的・関数型
    • Kotlin 2011年 静的
    • Ceylon 2011年 静的
    • Dart 2011年 静的・関数型 
    • Elixir 2011年 動的・関数型
    • Julia 2012年 動的・関数型・多重ディスパッチ
    • TypeScript 2012年 静的と動的・関数型
    • Swift 2014年 静的・プロトコル指向
    • Raku 2015年 静的と動的

    用語一覧[編集]

    ここでは日本語ページ化されている項目のみ列挙している。

    脚注[編集]

    [脚注の使い方]
    1. ^ Kindler, E.; Krivy, I. (2011). Object-Oriented Simulation of systems with sophisticated control. International Journal of General Systems. pp. 313–343. 
    2. ^ Lewis, John; Loftus, William (2008). Java Software Solutions Foundations of Programming Design 6th ed. Pearson Education Inc.. ISBN 978-0-321-53205-3 , section 1.6 "Object-Oriented Programming"
    3. ^ McCarthy, J.; Brayton, R.; Edwards, D.; Fox, P.; Hodes, L.; Luckham, D.; Maling, K.; Park, D. et al. (March 1960). LISP I Programmers Manual. en:Boston, en:Massachusetts: Artificial Intelligence Group, en:M.I.T. Computation Center and Research Laboratory. p. 88f. オリジナルの17 July 2010時点におけるアーカイブ。. https://web.archive.org/web/20100717111134/http://history.siam.org/sup/Fox_1960_LISP.pdf. "In the local M.I.T. patois, association lists [of atomic symbols] are also referred to as "property lists", and atomic symbols are sometimes called "objects"." 
    4. ^ McCarthy, John; Abrahams, Paul W.; Edwards, Daniel J.; Hart, swapnil d.; Levin, Michael I. (1962). LISP 1.5 Programmer's Manual. en:MIT Press. p. 105. ISBN 978-0-262-13011-0. https://archive.org/details/lisp15programmer00john/page/105. "Object — a synonym for atomic symbol" 
    5. ^ a b Dr. Alan Kay on the Meaning of "Object-Oriented Programming"” (2003年). 2010年2月11日閲覧。
    6. ^ Sutherland, I. E. (1963年1月30日). “Sketchpad: A Man-Machine Graphical Communication System”. Technical Report No. 296, Lincoln Laboratory, Massachusetts Institute of Technology via Defense Technical Information Center (stinet.dtic.mil). 2019年7月17日閲覧。
    7. ^ The Development of the Simula Languages, en:Kristen Nygaard, en:Ole-Johan Dahl, p.254 Uni-kl.ac.at
    8. ^ Ross, Doug. “The first software engineering language”. LCS/AI Lab Timeline. MIT Computer Science and Artificial Intelligence Laboratory. 2010年5月13日閲覧。
    9. ^ a b c Holmevik, Jan Rune (1994). “Compiling Simula: A historical study of technological genesis”. IEEE Annals of the History of Computing 16 (4): 25–37. doi:10.1109/85.329756. オリジナルの30 August 2017時点におけるアーカイブ。. https://web.archive.org/web/20170830065454/http://www.idi.ntnu.no/grupper/su/publ/simula/holmevik-simula-ieeeannals94.pdf 2018年3月3日閲覧。. 
    10. ^ {{Cite book|last = Dahl |first = Ole Johan|year = 2004 |chapter-url = http://www.mn.uio.no/ifi/english/about/ole-johan-dahl/bibliography/the-birth-of-object-orientation-the-simula-languages.pdf |doi = 10.1007/978-3-540-39993-3_3|access-date =3 March 2018 |chapter = The Birth of Object Orientation: The Simula Languages|title = From Object-Orientation to Formal Methods|volume = 2635|pages = 15–25|series = Lecture Notes in Computer Science|isbn = 978-3-540-21366-6|citeseerx = 10.1.1.133.6730}|access-date = 21 October 2021}
    11. ^ Nygaard, Kristen (1978). “The Development of the SIMULA Languages”. ACM SIGPLAN Notices 13 (8): 245–272. doi:10.1145/960118.808391. https://doi.org/10.1145/960118.808391 2021年10月22日閲覧。. 
    12. ^ Bertrand Meyer (2009). Touch of Class: Learning to Program Well with Objects and Contracts. Springer Science & Business Media. pp. 329. Bibcode2009tclp.book.....M. ISBN 978-3-540-92144-8 
    13. ^ Kay, Alan. “The Early History of Smalltalk”. 2007年9月13日閲覧。
    14. ^ “At Utah sometime after Nov 66 when, influenced by Sketchpad, Simula, the design for the ARPAnet, the Burroughs B5000, and my background in Biology and Mathematics, I thought of an architecture for programming. It was probably in 1967 when someone asked me what I was doing, and I said: "It's object-oriented programming".”Alan Kay on the Meaning of “Object-Oriented Programming”
    15. ^ https://wiki.c2.com/?MichaelFeathers
    16. ^ Abadi, Martin、Cardelli, Luca『A Theory of Objects』Springer-Verlag New York, Inc.、1996年。ISBN 978-0-387-94775-4

    関連項目[編集]