「オブジェクト指向プログラミング」の版間の差分
タグ: 取り消し |
Shionomisaki2458 (会話 | 投稿記録) m 仮リンクの修正 |
||
(36人の利用者による、間の359版が非表示) | |||
1行目: | 1行目: | ||
{{翻訳中途|[[:en:Object-oriented programming]](13:57, 15 November 2021 UTC)の翻訳|date=2021年11月}} |
|||
{{複数の問題 |
|||
{{プログラミング・パラダイム}} |
|||
|独自研究=2018年2月 |
|||
|正確性=2019年2月 |
|||
|出典の明記=2019年2月 |
|||
}} |
|||
{{プログラミング言語|index=おふしえくとしこうふろくらみんく}} |
|||
[[ファイル:Object oriented design object.jpg|境界|右|フレームなし]] |
|||
'''オブジェクト指向プログラミング'''(オブジェクトしこうプログラミング、{{Lang-en-short|''object-oriented programming''}}、略語:OOP)は、[[オブジェクト指向]]の[[プログラミングパラダイム|考え方]]<ref>コンピュータ・プログラミングのパラダイムについては『新しいプログラミング・パラダイム』などを参照: http://www.kyoritsu-pub.co.jp/bookdetail/9784320024939</ref>を取り入れた[[プログラミング (コンピュータ)|コンピュータプログラミング]]手法である。[[オブジェクト (プログラミング)|オブジェクト]]とは大まかに言うとデータ([[変数 (プログラミング)|変数]]または[[プロパティ (プログラミング)|プロパティ]])とコード([[関数 (プログラミング)|関数]]または[[メソッド (計算機科学)|メソッド]])の複合体を意味しているが、その詳細については様々な解釈が存在する。OOPに基づくプログラムはこの[[オブジェクト (プログラミング)|オブジェクト]]の集合として組み立てられる事になるが、その実装スタイルもまた千差万別である。 |
|||
'''オブジェクト指向プログラミング'''(オブジェクトしこうプログラミング、{{Lang-en-short|object-oriented programming}}, OOP)とは、「[[オブジェクト (プログラミング)|オブジェクト]]」という概念に基づいた[[プログラミングパラダイム]]の一つである。 |
|||
オブジェクト指向プログラミングという言葉自体は計算機科学者[[アラン・ケイ]]が作り出したものである。彼は1967年に公開された[[Simula|Simula67]]の[[クラス (コンピュータ)|クラス]]と[[オブジェクト (プログラミング)|オブジェクト]]を備えた言語仕様を見た際に''object-orientedという造語を咄嗟に口にしたとされ、その造語は''ケイ自身が1972年から80年にかけて開発した[[Smalltalk]]の言語設計を説明する中で初めて用いられて世間に知られるようになった。なお[[Smalltalk]]における、あらゆるプログラム内要素をオブジェクトとして扱い、[[メッセージパッシング]]でコミュニケーションさせるというケイ発案のオブジェクト指向の実践は、マシンパワーやリソースを必要としたため誰もがその恩恵に預かれたわけではなかった。1983年に公開された[[C++]]が契機となり、OOPはまた違った角度から注目されるようになった。最終的にこの[[C++]]の設計スタイルが物議を醸しながらもOOPの主流となるに到り、同時にOOPの三原則とされる[[カプセル化]]、[[継承 (プログラミング)|継承]]、[[ポリモーフィズム|多態性]]の[[プログラミングパラダイム]]が確立されている。 |
|||
OOPでは、相互に作用するオブジェクトを組み合わせてプログラムを設計する{{sfn|Kindler|Krivy|2011}}{{sfn|Lewis|Loftus|2008|loc=§1.6 "Object-Oriented Programming"}}。 |
|||
== 特徴 == |
|||
プログラミングパラダイムとしてのオブジェクト指向の確立は紆余曲折を経ており(後述)その詳細の解釈も様々であるが、一定の枠組みとなる三つの原則(''fundamental principle'')が存在し、それに従った言語仕様を総体的または部分的に備えたプログラミング言語がオブジェクト指向準拠と判別される。1~3はオブジェクト指向プログラミングの三原則とされるものであり[[C++]]を契機にして提唱された。4を加えて四本の柱(''pillar'')とする考えもある。 |
|||
OOPの方法として、[[クラスベース]]OOPと[[プロトタイプベース]]OOPがある。 |
|||
5~7は[[Smalltalk]]が提唱する元祖オブジェクト指向のコンセプトであり、この三者は相互に関連して始めて一つの意味を表現している。その真髄はオブジェクトを媒体にしてコードとデータの融合を目指した高度な抽象化または代数化である。元祖オブジェクト指向は哲学的側面が強いものであり、それを実用的に演繹したものが1~3であると考える事も出来る。 |
|||
クラスベースOOPでは、オブジェクトが属する集合として[[クラス (コンピュータ)|クラス]]を定義し、クラス定義からその[[インスタンス]]としてオブジェクトを生成する。 |
|||
プロトタイプベースOOPでは既存のオブジェクト(プロトタイプ)を複製し、プロトタイプの複製に変更を加えることで様々な対象を表すオブジェクトを生成する。 |
|||
#[[カプセル化]](''encapsulation'') |
|||
#[[継承 (プログラミング)|継承]](''inheritance'') |
|||
#[[ポリモーフィズム|多態性]](''polymorphism'') |
|||
#*アドホック多態性(''ad hoc polymorphism'') |
|||
#**[[多重定義|関数オーバーロード]](''function overloading'') |
|||
#**[[多重定義|演算子オーバーロード]](''operator overloading'') |
|||
#*パラメータ多態性(''parameter polymorphism'') |
|||
#**[[ジェネリックプログラミング|ジェネリック関数]](''generic function'') |
|||
#**[[ジェネリックプログラミング]](''generic programming'') |
|||
#*[[派生型|サブタイプ多態性]](''subtyping'') |
|||
#**[[仮想関数]](''virtual function'') |
|||
#**動的ディスパッチ(''dynamic dispatch'') |
|||
#**[[ダブルディスパッチ]](''double dispatch'') |
|||
#**[[多重ディスパッチ]](''multiple dispatch'') |
|||
#[[抽象化 (計算機科学)|抽象化]](''abstraction'') |
|||
#[[メッセージ (コンピュータ)|メッセージング]](''messaging'') |
|||
#ローカル保持(''local retention, protection, hiding of state-process'') |
|||
#[[動的束縛|遅延バインディング]](''late binding'') |
|||
=== カプセル化 === |
|||
任意のデータ(変数、プロパティ)群と、それを参照ないし変更するコード(関数、メソッド)群をひとまとめにしてオブジェクトとし、オブジェクト内のデータ群は外部からはアクセスできず隠蔽され、外部公開されたコードを通してのみアクセス可能にした仕組みがカプセル化と呼ばれる。より詳しい解釈については様々だが、オブジェクト指向におけるカプセル化は、基本的に内部隠蔽に焦点を当てたパラダイムである。開発規模の拡大に伴い解決の難しいバグ原因の大半は、データの予期せぬ変化とデータ間の予期せぬ不整合である事が経験則で知られるようになったので、データを変えたコードの位置特定を容易にする為の手段だった。データ直接参照の禁止は予期せぬデータの読み取りを抑止するだけでなく、いわゆる抽象化の一手段も兼ねていた。データを読み取る際にワンクッションの仲介コードを置く事で実行環境の変化に合わせた柔軟なデータ表現を可能にした。ただしこのワンクッション制度は安全性と引き換えにコード記述量を大きくするので、特定のデータとコードに対しては便宜的に直接アクセスを解禁する仕組みも生まれ、これはアクセス権限と呼ばれた。 |
|||
カプセル化を推し進めたものとして'''プロトコル'''(''protocol'')がある。これはオブジェクト内部を全隠蔽し、抽象メソッドをまとめた純粋抽象クラスで表現されるインターフェース・オブジェクトを通してアクセスする仕組みを指した。オブジェクトそのものにワンクッションを置いた制度とも言える。プロトコルはオブジェクトの安全な公開を実現し、共同開発とコンポーネント開発に適したものとされた。プロトコルは後述の多態性にも関連しており、特に動的ディスパッチを表現するメカニズムにもなった。 |
|||
=== 継承 === |
|||
継承の元々の趣旨はオブジェクトの体系化である。ここでの体系化とは多様な要素をそれぞれ共通と特有の分節構成にし、共通部分から特有部分を派生させる形で関連付ける枝葉状の展開構図に投影する行為を指した。構造体の定義増加で発生しやすい似たようなデータ群の重複に伴う冗長さとその整合性維持の手間隙を解決する為の手段であった。構造体=オブジェクトを複数の階層に分け、共通のデータ集合を親階層とし、特有のデータ集合を子階層として、子階層に親階層へのリンクを持たせて連結する構造にした。A階層から成る親オブジェクトから派生した子オブジェクトはA+B階層として構成され、これが継承と呼ばれた。コードから参照されたデータがB階層に無い時は、次のA階層に有るか探す仕組みとなり、この連鎖によって傍からは一つのオブジェクトとして存在した。データと同様に共通のメソッド群も親階層にまとめられた。その応用として抽象メソッド(=仮想関数)だけの階層を独立させたインターフェースまたは純粋抽象クラスがあり、これを親階層として継承(実装)するのは'''[[派生型|サブタイピング]]'''(''subtyping'')となった。サブタイピングは後述の多態性のメカニズムの一つでもある。なお、派生クラスで任意の機能を追加できる仕組みはコードの再利用性を高めるとも考えられたが、深い継承はクラス構造の把握を困難にするという欠点が明らかになったのでこれは否定された。継承による再利用性はクラスライブラリの使用範囲内に留まっているのが現状である。 |
|||
なお、子階層の次のリンク先となる親階層は一本だけでなく複数本持つ事も出来るので、複数の親階層+子階層によるオブジェクト構成は'''多重継承'''と呼ばれた。子階層が持つ親階層アドレスは一般にリスト化されており、自身に無いデータはリスト先頭の親階層から順々に検索された。その親階層が多重継承されてる場合も同様であり、それぞれの枝分かれには深さ優先検索が用いられた。前述のサブタイピングは多重で行われる事が多い。 |
|||
=== 多態性 === |
|||
アドホック多態性は単にソースコードの記述を一部自動化するものである。'''関数オーバーロード'''は引数の並び方パターンによって同じ名前のメソッドをコンパイル時に自動的に差別化する機能である。'''演算子オーバーロード'''は、扱う数値の型に従って宣言された演算記号を関数名と見なすようにし、単項演算子なら右の数値を第一引数とし、二項演算子なら左右の数値をそれぞれ第一第二引数として関数呼び出しのコードが生成されるという仕組みだった。丸括弧の演算子は関数オブジェクトの表現として使用出来た。これらは静的な多態性とされる。 |
|||
パラメータ多態性もソースコードの記述を一部自動化するものである。関数&クラスのコード内の特定の型部分をワイルドカードにして記述しておき、ソースコード内で具体的な型の指定と共に関数&クラスの呼び出しが記述されると、その型を先のワイルドカードに当てはめた関数&クラスのコードがコンパイル時に自動生成されるという機能だった。&の前者は'''ジェネリック関数'''と呼ばれ、後者はより広い範囲を扱う事から'''ジェネリックプログラミング'''と名付けられた。これらも静的な多態性に位置付けられている。 |
|||
サブタイプ多態性は動的なものである。最も初期のOOPであるSimula67は、シミュレーション内で扱う多種多様なオブジェクトを継承によって体系化したが、コード部分の細かな違いは共通スーパークラスに属する共通プロシージャ内の分岐フローで処理していた。サブクラスの数だけ分岐構文が増える頻雑さを解消するために、共通プロシージャをただの[[仮想関数テーブル]]にしてサブクラスの実装時に同名プロシージャのアドレスを収納させ、共通プロシージャ呼び出し時にそのアドレスへジャンプするという機能が考案された。[[仮想関数テーブル]]はプロシージャの仮想的存在と見なされたので、この機能は'''仮想関数'''と呼ばれた。'''動的ディスパッチ'''はSmalltalkのオブジェクト設計に由来するものであり、その実装の仕方は様々でやや曖昧な仕様でもある。メッセージを受け取ったレシーバーがオブジェクト内部で動的な状態に従い動的な処理を行って結果を返すというランタイム環境上のプロセスが後に動的ディスパッチのカテゴリで括られた。[[分散コンピューティング]]を表現する[[Object Request Broker|オブジェクト間通信]]とそれに基づく[[ソフトウェアコンポーネント]]も動的ディスパッチに該当するものである。'''多重ディスパッチ'''は動的な関数オーバーロードに近いものである。関数コール時または関数ブロック内で、それぞれの引数が動的に型審査されて型変化(''dynamic casting'')された後に、その引数パターンに対応した同名関数または分岐ルーチンに処理が移行されるという動的変化プロセスを指した。'''ダブルディスパッチ'''は多重ディスパッチの亜流的存在であり、二通りの考え方がある。動的型審査および型変化されるBオブジェクトを単一引数にしてAオブジェクトの仮想関数メソッドを呼び出す形態と、多重ディスパッチに用いる引数を二つに限定した形態である。いずれも実行時状態に応じた動的変化プロセスとなった。これは主にデータ集合を対象にして分類、解析、作用といった処理を連続的または再帰的に行うアルゴリズムで用いられた。 |
|||
=== 抽象化 === |
|||
純粋抽象クラスの仕組みがこれに相当する。実例としては[[ソフトウェアコンポーネント]]及び[[Java]]などのプログラミング言語で用いられている[[インタフェース (抽象型)|インターフェース]]がある。この抽象化は、カプセル化の{{仮リンク|.プロトコル|en|Protocol (object-oriented programming)|label=}}、継承の[[派生型|サブタイピング]]、多態性の仮想関数をまとめたパラダイムと考える事が出来る。 |
|||
[[C++]]開発者の[[ビャーネ・ストロヴストルップ]]は、広義のオブジェクト指向の主要サポート案件として抽象化、継承、実行時多態性(''run-time polymorphism'')の三点を挙げていた。抽象化は同時に完全な内部隠蔽になるので、コンクリートクラスの中途半端な内部隠蔽ではなく、純粋抽象クラスのプロトコルを重視していた事が分かる。 |
|||
=== メッセージング === |
|||
メッセージングは哲学的側面が強いパラダイムである。仕組み的には、オブジェクト(=インスタンス)のメソッドコール、または[[Object Request Broker|オブジェクト間通信]]におけるリモートメソッドコールと同じものと考えてよいが、メッセージングのパラダイム下では、イメージ的にオブジェクトそのものをメソッドとしてコールする点が異なっている。それは各オブジェクトが一般にレシーバーと呼ばれるデフォルトメソッドを持つ事で実現されている。オブジェクトのコールとは、このレシーバーをコールするのと同義となる。引数無しでコールされる事はなく、基本的に一つのオブジェクトが引数となってコールされる。これも留意すべき点である。元祖オブジェクト指向では「''EverythingIsAnObject''」の通り、[[プリミティブ型|プリミティブ]]から[[構造体|データストラクチャ]]、[[コードブロック]]まであらゆるプログラム要素がオブジェクトとされる。ここにオブジェクトA、Bがあるとすると、メッセージングの基本構文は「A B」のようになる。これは「Bを引数にしてAを呼び出す」の意味であり、イメージ的に「Aに対してBというメッセージを送る」と形容される。引数Bを受け取ったAのレシーバー内で任意の処理が行われた後に結果値としてのオブジェクトが返される。Aそのものが返される事もあれば、別のオブジェクトが返される事もある。この流れがメッセージングと呼ばれるものである。返値オブジェクトに対して別のメッセージを送る事も可能であり、また返値オブジェクトをメッセージにして別のオブジェクトに送る事も出来る。こうしたメッセージングの連鎖はAのレシーバー内でも同様に行なわれる。メッセージング・パラダイム下でのオブジェクトは言わば独自の記憶を備えた変換式であり、これらオブジェクトのコミュニケーションとは[[高階関数]]と[[第一級関数]]の仕組みと同じものである。メッセージング・パラダイムの本質はオブジェクトの代数(''algebra'')化であり、その代数値は前述のメッセージングの連鎖による結果値である。メッセージングを行なうオブジェクトもまたメッセージング連鎖の集合体という事になる。それはただの[[プリミティブ|プリミティブ値]]であっても決して例外ではない。レシーバーでの処理をコードとすると、メッセージング・パラダイム下でのデータはメッセージング連鎖によるコードの集合体であり、その各コードは他のデータ群を参照しており、その各データもまたコードの集合体~という風になる。勿論最終的には根っことなるオブジェクトの定形データに行き着いてそれが値算出の原点になるが、こうなるとイメージ的にコードとデータが融合して両者の区別はなくなる。オブジェクトは抽象化の一形態である代数的(''algebraic'')存在なので、代数計算と同様に理念的には単体で成り立つ事はなく、二つのオブジェクトが出会うメッセージングによって始めて一定のプロセスが発生し、または一つのデータが体現される。これが引数無しでもよいメソッドと引数が要るメッセージングの明確な違いである。 |
|||
なお、実装面では便宜上の理由から、メッセージングの際の引数オブジェクトにはセレクタを付けるのが許容されている。大抵は「A ''selector'':B」の様になる。セレクタはメソッド名と同義であり、引数オブジェクトに貼られるラベルと考えていいものである。セレクタによってレシーバー外の対応メソッドに自動分岐されるのでコーディングが簡便になる。[[演算子]]も事実上のセレクタであり「5+3」は、+セレクタを貼った3オブジェクトを5に送ると解釈できる。括弧記号はコンパイラのためのただの[[ディレクティブ]]となる。メッセージングは二つのオブジェクトが出会った時点で発生するプロセスなので引数は常に一つであり、複数の引数を用いたい場合はパーシャルアプリケーションまたは[[カリー化]]を適用するべきであるが、これは困難なコーディングになる事が多いので、セレクタによる[[パターンマッチング]]的な各メソッドへの自動分岐も許容されている。 |
|||
このメッセージングのパラダイムは様々な理由から広くは認知されず、やがてその言葉だけが一人歩きするようになって本来の定義からシフトし、前述のレシーバーの仕組み自体がメッセージングと見なされるようにもなり、[[Object Request Broker|オブジェクト間通信]]で行なわれるバイトデータ列の送受信もメッセージングの代表例とされるようになった。また、インスタンスの単純なメソッド呼び出しもメッセージングであると説明される事もある。この様にメッセージングの本質は見失われながらも、その側面的仕様は数々のOOP言語に導入されてもいる。 |
|||
=== ローカル保持 === |
|||
{{節スタブ}} |
|||
=== 遅延バインディング === |
|||
{{節スタブ}} |
|||
広く使われているプログラミング言語の多く、例えば[[C++]]や[[Java]]や[[Python]]などは、[[マルチパラダイムプログラミング言語|マルチパラダイム]]であるが、程度の差はあれ、オブジェクト指向プログラミングをサポートしており、大抵は[[命令型プログラミング|命令型]]や[[手続き型プログラミング]]との組み合わせで用いられる。 |
|||
== 歴史 == |
== 歴史 == |
||
オブジェクト指向プログラミングという考え方が生まれた背景には、計算機の性能向上によって従来より大規模な[[ソフトウェア]]が書かれるようになってきたということが挙げられる。大規模なソフトウェアが書かれコードも複雑化してゆくにつれ、ソフトウェア開発コストが上昇し、[[1960年代]]には「[[ソフトウェア危機]] ({{Lang|en|software crisis}})」といったようなことも危惧されるようになってきた。そこでソフトウェアの[[再利用 (プログラミング)|再利用]]、[[部品化 (プログラミング)|部品化]]といったようなことを意識した仕組みの開発や、[[ソフトウェア開発工程]]の体系化('''[[ソフトウェア工学]]''' ({{Lang|en|software engineering}}) の誕生)などが行われるようになった。 |
|||
[[File:oop-uml-class-example.png|frame|right|[[統一モデリング言語|UML]]による[[クラス (コンピュータ)|クラス]]の表記法。この {{code|Button}} クラスは、データを表す[[変数 (プログラミング)|変数]](図中 {{code|xsize}} など)と[[メソッド (計算機科学)|関数]](図中 {{code|draw()}} など)を持つ。一般的なクラスは[[継承 (プログラミング)|継承]]により[[サブクラス (計算機科学)|サブクラス]]を持つことができる。また、オブジェクトはクラスの[[インスタンス]]である。]] |
|||
<!-- 以上、[[en:Object-oriented programming]] oldid=1047374345 の翻訳 --> |
|||
[[アラン・ケイ]]によれば “{{en|object-oriented}}”([[オブジェクト指向]])という言葉は、1967年ごろケイ自身が考案したものであるという{{sfn|Meaning|2003}}。しかし、現在のオブジェクト指向プログラミングという文脈における「オブジェクト」や「指向」を表す用語が初めて登場したのは、1950年代後半から1960年代前半にかけての[[マサチューセッツ工科大学|マサチューセッツ工科大学(MIT)]]においてである。 |
|||
1960年代初頭の[[人工知能]]グループ界隈では、「オブジェクト」はプロパティ(属性)を持つ個体識別可能なアイテム([[LISP]]の atom)を意味していた{{sfn|LISP 1 Programmers Manual|1960|p=88f}}{{sfn|LISP 1.5 Programmers Manual|1962|p=105}}。 |
|||
後にケイは、1966年にLISPの内部構造を詳細に理解したことが彼の考え方に強い影響を与えたと述べている{{sfn|Meaning|2003}}。 |
|||
{{Quote box |
|||
このような流れの中で、プログラムを構成するコードとデータのうち、コードについては[[プロシージャ|手続き]]や[[関数 (プログラミング)|関数]]といった仕組みを基礎に整理され、その構成単位を[[ブラックボックス]]とすることで再利用性を向上し、部品化を推進する仕組みが提唱され'''[[構造化プログラミング]]''' ({{Lang|en|structured programming}}) として{{要出典範囲|date=2019年2月|[[1967年]]}}に[[エドガー・ダイクストラ]] ({{Lang|en|Edsger Wybe Dijkstra}}) らによってまとめあげられた(プログラミング言語の例としては[[Pascal]] [[1971年]])。なお、それに続けて「しかしデータについては相変わらず主記憶上の記憶場所に置かれている限られた種類の[[基本データ型]]の値という比較的低レベルの抽象化から抜け出せなかった。これはコードはそれ自身で意味的なまとまりを持つがデータはそれを処理するコードと組み合わせないと十分に意味が表現できないという性質があるためであった。」といったように、ほぼ間違いなく説明されている。 |
|||
|quote = 私は、オブジェクトとは、生物の細胞やネットワーク上の個々のコンピュータのようもの、そしてそれらのコミュニケーションは専らメッセージによって行なわれるもの、と考えていました (つまり、メッセージングは最初から存在していたのですが、プログラミング言語でメッセージングを実用的かつ効率的に行う方法を見つけるまでには時間がかかりました)。 |
|||
|author = アラン・ケイ |
|||
|source = {{harv|Meaning|2003}} |
|||
|width = 50% |
|||
}} |
|||
MITにおける初期の例としては、この他にも、1960年から1961年にかけて[[アイバン・サザランド]]が作成した[[Sketchpad]]が挙げられる。サザランドは、1963年の技術レポートの用語集 (Sketchpadに関する自身の博士論文をもとにしたもの)で、グラフィカルなインタラクションに特化しているとはいえ「オブジェクト」と「インスタンス」の概念を定義している (クラスの概念は"master"または"definition"として把握されている)。{{sfn|Sutherland|1963}} |
|||
そこでデータを構造化し、ブラックボックス化するために考え出されたのが、データ形式の定義とそれを処理する手続きや関数をまとめて一個の構成単位とするという考え方で'''[[モジュール]]''' ({{Lang|en|module}}) と呼ばれる概念である([[プログラミング言語]]の例としては[[Modula-2]] 1979年)。しかし定義とプログラム内の実体が一対一に対応する手続きや関数とは異なり、データはその形式の定義に対して値となる実体([[インスタンス]]と呼ばれる)が複数存在し、各々様々な寿命を持つのが通例であるため、そのような複数の実体をうまく管理する枠組みも必要であることがわかってきた。そこで単なるモジュールではなく、それらのインスタンスを整理して管理する仕組み(例えば[[クラス (コンピュータ)|クラス]]とその[[継承 (プログラミング)|継承]]など)まで考慮して生まれたのが[[オブジェクト (プログラミング)|オブジェクト]]という概念である(プログラミング言語の例としては1967年の[[Simula|Simula 67]]<!--言語機能としての「クラス」はSimula 67から-->)。 |
|||
また、MIT版の[[ALGOL]]であるAED-0では、データ構造 (この言語の方言では"plexes"と呼称)と手続きを直接結びつけ、後に「メッセージ」、「メソッド」、「メンバ関数」と呼ばれるようなものの萌芽がみられる。{{sfn|Nygaard|Dahl|1978}} |
|||
1962年、[[クリステン・ニゴール]]は{{仮リンク|ノルウェー計算センター|en|Norwegian Computing Center}}でシミュレーション言語のプロジェクトを開始した。これは彼が以前に用いた[[モンテカルロ法]]と実世界のシステムを概念化する仕事に基づくものであった。[[オーレ=ヨハン・ダール]]が正式にプロジェクトに参加し、[[UNIVAC I]] (UNIVAC 1107) 上で動作する[[Simula]]プログラミング言語が設計された。Simulaは、[[クラス (コンピュータ)|クラス]]や[[オブジェクト (プログラミング)|オブジェクト]]、継承、[[ダイナミックバインディング]]など、今日のオブジェクト指向プログラミングには不可欠である重要な概念を導入した。{{sfn|Holmevik|1994}} |
|||
Simulaのオブジェクトとクラスというアイデアは異なる二つの概念に継承される。一つはシステム全てをオブジェクトの集合と捉え、オブジェクトの相互作用を'''メッセージ'''に喩えた「[[オブジェクト指向]]」である。オブジェクト間の相互作用をメッセージの送受と捉えることで、オブジェクトは受信したメッセージに見合った手続き単位(≒関数)を自身で起動すると考える。結果オブジェクトは自身の持つ手続きのカプセル化を行うことができ、メッセージが同じでもレシーバオブジェクトによって行われる手続きは異なる――[[ポリモーフィズム|多相性]](ポリモーフィズム)を実現した(このメッセージを受け実行される手続き単位は、メッセージで依頼されたことを行うための「手法」の意味で[[メソッド (計算機科学)|メソッド]]と呼ばれる)。この思想に基づき作られたのが[[Smalltalk]]([[1972年]])であり、[[オブジェクト指向]]という言葉はこのとき[[アラン・ケイ]]によって作られた。 |
|||
Simulaはまた、プログラミングにおける{{仮リンク|データ保全|en|data security}}を考慮して設計されたものでもあった。プログラミングのデータ保全のために[[参照カウント]]による検出プロセスが実装されたのに加え、最終手段として[[ガベージコレクション|ガベージコレクタ]]が[[主記憶装置]](メモリ)内の使用されていないオブジェクトを削除するようになっていた。しかし、データオブジェクトの概念は1965年には既に確立されていたものの、プライベートやパブリックといった[[変数 (プログラミング)|変数]]の[[スコープ (プログラミング)|スコープ]]のレベルによるデータのカプセル化については、アクセスする手続きもまた隠蔽できなければならなかったため、Simulaでは実装されなかった。{{sfn|Dahl|2004}} |
|||
初期の段階では、Simulaはプログラミング言語[[ALGOL]] 60のための手続きパッケージとされていた。しかし、ALGOLによる制約に不満を感じた研究者たちは、UNIVAC ALGOL 60コンパイラを使用した本格的なプログラミング言語としてSimulaを開発することにした。ダールとニゴールは1965年から1966年にかけてSimulaの普及に尽力し、スウェーデン、ドイツ、[[ソビエト連邦]]などでSimulaの使用が増加した。1968年には、[[バロース B5000]]上で広く利用されるようになり、後には[[ウラル・コンピュータ|URAL-16コンピュータ]]上にも実装された。1966年、ダールとニゴールはSimulaの[[コンパイラ]]を書いた。彼らは、{{仮リンク|SIMSCRIPT|en|SIMSCRIPT}} (自由形式の英語的な汎用シミュレーション言語)を実装に用いて、[[アントニー・ホーア]]のレコード・クラス概念を取り入れることに熱心に取り組んだが、彼らは、一般化されたプロセスの概念として、レコード・クラスの属性を保持する層と、接頭辞 (prefix) の系列を保持する層の二層構造とする方式に辿り着いた。 |
|||
一方、Smalltalkとは別にSimulaの影響を受け作られた[[C++]]([[1979年]])は[[抽象データ型]]のスーパーセットとしてのクラス、オブジェクトに注目し、オブジェクト指向をカプセル化、継承、多相性をサポートするものと再定義した(その際、実行時速度重視およびコンパイラ設計上の制約により、変数メタファである[[動的束縛]]の特徴は除外された)。これらは当初[[抽象データ型]]、[[派生]]、[[メソッド (計算機科学)#仮想関数|仮想関数]]と呼ばれ、オブジェクトのメンバ関数を実体ではなくポインタとすることで、継承関係にあるクラスのメンバ関数の[[オーバーライド]](上書き)を可能にしたことで、多相性を実現した(この流儀では'''メッセージメタファ'''はオブジェクト指向に必須ではないものと定義し、オブジェクトの持つ手続きをメソッドとは呼ばず[[メソッド (計算機科学)|メンバ関数]]と呼ぶ)。この他、Smalltalkにある[[動的束縛]]の類似的な機能としてオーバーロード([[多重定義]])が実装されている。 |
|||
接頭辞の系列を通じて、プロセスは先行する定義を参照し、それらの属性を追加することができる。このようにしてSimulaは、クラスとサブクラスの階層を導入し、これらのクラスからオブジェクトを生成することを可能にする方法を導入することとなった。{{sfn|Nygaard|Dahl|1978}} |
|||
1972年には[[System/360|IBM System/360]]および[[System/370|IBM System/370]]の[[IBMメインフレーム]]用にSimula 67コンパイラが完成{{sfn|Holmevik|1994}}。同年、フランスの[[CII 10070]]および[[CII Iris]] 80[[メインフレーム]]用のSimula 67コンパイラが無償で提供された。1974年には、Simulaユーザー会は23カ国のメンバーを有するまでになっていた。1975年初頭、[[PDP-10|DECsystem-10]]メインフレームファミリー用のSimula 67コンパイラが無償でリリースされ、同年8月までにDECsystem-10のSimula 67コンパイラは28サイトにインストールされた (そのうちの22サイトは北米)。オブジェクト指向のプログラミング言語としてSimulaは、貨物港における船舶と積載貨物の動きを調査・改善するための研究のような、物理モデリングの研究に携わる研究者に主に利用されていた{{sfn|Holmevik|1994}}。 |
|||
Smalltalkはこの「全てをオブジェクトとその相互作用で表現する」というデザインに立ち設計されたため、全てをファイルと捉える'''ファイル指向[[オペレーティングシステム]]'''からの脱却と、プログラムをフロー制御された手続きと捉える'''手続き型言語'''からの脱却が行われた。そのためSmalltalkは自身が'''オブジェクト指向オペレーティングシステム'''でもあること、メッセージ・パッシングなどの特徴を持った。これは当時のプログラム言語としては特異的であり、[[ガベージコレクション|ガベージコレクタ]]を必要とし、高度な最適化が試される前のバイトコード[[インタプリタ]]で実行される処理の重さも手伝って先進的ではありながら普及しがたいものであると捉えられた。また、メッセージでの多相性は、変数へのオブジェクトの[[動的束縛]]が前提となるため、静的型チェック機構でのサポートが難しく、C++等の実行時性能重視の言語にとって実装から除外すべき特徴となった。 |
|||
1970年代、[[パロアルト研究所|Xerox パロアルト研究所(PARC)]]において、[[アラン・ケイ]]、[[ダン・インガルス]]、[[アデル・ゴールドバーグ]]らによって、プログラミング言語[[Smalltalk]]の最初のバージョンが開発された。Smaltalk-72はプログラミング環境を含み、[[動的型付け]]であり、当初は[[コンパイラ|コンパイル]]してからの実行ではなく[[インタプリタ]]実行であった。Smalltalkは、言語レベルでのオブジェクト指向の適用と、グラフィカルな開発環境で注目されたが、Smalltalkが様々なバージョンを経て成長するにつれ、この言語への関心も高まっていった{{sfn|Meyer|2009}}。 |
|||
C++の創始者[[ビャーネ・ストロヴストルップ]]は、Smalltalkが目指したある種の理想の追求には興味が無く、現用としての実用性を重視した。そのため、C++の再定義した「オブジェクト指向」は既存言語の拡張としてオブジェクト指向機能を実装できることでブレイクスルーを迎え急速に普及する。Smalltalkが単なるメソッドの動的呼び出しをメッセージ送信に見立て、呼び出すメソッドが見つからないときのみメッセージをハンドリングできるようにした「省コスト版」の機構を発明し以降それを採用するに至った経緯も手伝って、'''メッセージ送信'''という考え方はやや軽視されるようになり、オブジェクト指向とはC++の再定義したものと広く認知されるようになった。 |
|||
SmalltalkはSimula 67で導入されたアイデアの影響を受けてはいるものの、クラスを動的に生成・変更できるなど、完全に動的なシステムとして設計された{{sfn|Kay|1993}}。 |
|||
1970年代、Smalltalkは[[LISP#LISPの歴史|Lispコミュニティ]]に影響を与え、Lispコミュニティは、[[Lispマシン]]を通じて開発者に紹介されたオブジェクトベースの技術を取り入れた。Lispの様々な拡張機能(LOOPS や{{仮リンク|Flavors|en|Flavors (programming language)}}などが導入した[[多重継承]]や[[Mixin]])の試みは、最終的に[[関数型プログラミング]]とオブジェクト指向プログラミングを統合し、{{仮リンク|メタオブジェクト・プロトコル|en|Metaobject protocol}}による拡張を可能にした[[Common Lisp Object System|Common Lispのオブジェクト指向システム]] (CLOS) へとつながった。 |
|||
[[1980年]]代後半に次々と生まれたオブジェクト指向分析・設計論は、[[Smalltalk]]を源流とするオブジェクト指向を基に組み立てられた。そのころSmalltalkは商用展開こそされていたが広く普及しているとは言えず、一般には[[C++]]での[[実装]]が多くを占めた。しかしC++はSmalltalkと思想的にかなり異なる点や、同様のことを実現する際の実装面での複雑さや制約が問題とされた。このニーズを受けC++の提示した抽象データ型にクラスを適用する現実的な考え方と親しまれたALGOL系の構文を踏襲しつつ、内部的には柔軟なSmalltalkのオブジェクトモデルを採用し、'''メソッド'''などの一部用語やリフレクション、実行時動的性などSmalltalk色も取り入れた[[Java]]が注目を集めた([[1995年]]に登場。元々はモバイル機器向け言語処理系として開発された)。程なくSmalltalkやSELFで達成された[[仮想機械|仮想マシン(バイトコードインタープリタ)]]高速化技術の転用により実用的速度を得、バランス感覚に長けたJavaの台頭によって[[オブジェクト指向開発]]に必要な要素の多くが満たされ、[[1990年代]]後半からオブジェクト指向は広く普及するようになった。 |
|||
1980年代には、メモリ上のオブジェクトをハードウェアでサポートするプロセッサ・アーキテクチャを設計する試みがいくつか行われたが、[[Intel iAPX 432]]や[[リン (企業)|Linn Smart]]、{{仮リンク|Rekursiv|en|Rekursiv}}など、いずれも商業的に成功しなかった。 |
|||
1981年、ゴールドバーグは[[バイト (雑誌)|Byte Magazine]] 8月号のSmalltalk特集号で、Smalltalkとオブジェクト指向プログラミングをより多くの人々に紹介した。 |
|||
== OOP言語一覧 == |
|||
1986年、[[Association for Computing Machinery|ACM]]が主催する第一回[[OOPSLA]]が開催され、予想に反して1,000人が参加した。1980年代半ばには、[[ITT (企業)|ITT]]でSmalltalkを使っていた[[ブラッド・コックス]]によって[[Objective-C]]が開発され、博士論文でSimulaを扱っていた[[ビャーネ・ストロヴストルップ]]よってオブジェクト指向の[[C++]]が作られた{{sfn|Meyer|2009}}。 |
|||
[[ファイル:History of object-oriented programming languages.svg|サムネイル|OOP言語の系譜|リンク=Special:FilePath/History_of_object-oriented_programming_languages.svg|代替文=]] |
|||
1985年には、[[バートランド・メイヤー]]も[[Eiffel]]の最初の設計を行った。ソフトウェアの品質に焦点を当てたEiffelは、純粋なオブジェクト指向プログラミング言語であり、ソフトウェアのライフサイクル全体をサポートする記法をもつ。メイヤーは、ソフトウェア工学とコンピュータサイエンスの少数の重要なアイデアに基づいたEiffelでのソフトウェア開発手法を{{仮リンク|オブジェクト指向入門|en|Object-Oriented Software Construction}}で解説している。Eiffelでは、メイヤーが開発した信頼性担保の機構である[[契約プログラミング]]が、開発手法と言語の双方に不可欠な要素となっている。 |
|||
オブジェクト指向を総体的または部分的にサポートする機能を備えたプログラミング言語の公開は、1980年代後半から顕著となった。OOP言語の分類法は複数あるが、Smalltalkをルーツとするメッセージパッシングの構文が重視されてるか否かで大別される事が多い。そうでないものがOOP言語の主流となっており「C++」「Java」「C#」「Swift」などがその代表とされる。メッセージパッシングを重視するOOP言語には「Smalltalk」「Objective-C」「Self」などがある。言語仕様の中でオブジェクト指向の存在感が比較的高い代表的なプログラミング言語を以下に列挙する。 |
|||
[[File:Tiobeindex.png|thumb|350px|[[:en:TIOBE index|TIOBE]] [[:en:Measuring programming language popularity|プログラミング言語の人気ランキング]]の2002年から2018年のグラフ。2000年代のオブジェクト指向言語[[Java]] (青)と[[手続き型プログラミング]]言語[[C言語|C]] (黒)の首位争いの様子]] |
|||
;[[Simula|Simula 67]] 1967年 |
|||
1990年代前半から半ばにかけて、オブジェクト指向プログラミングは、その技術をサポートするプログラミング言語が広く普及したことにより、[[プログラミングパラダイム]]として主要なものとなった。その中には、[[Microsoft Visual FoxPro|Visual FoxPro]] 3.0<ref group="注">1995年6月 Visual FoxPro 3.0, FoxPro は手続き型言語からオブジェクト指向言語へと進化した。Visual [[FoxPro]] 3.0では、データベースコンテナ、シームレスなクライアント/サーバー機能、ActiveXのサポート、OLEオートメーションとヌルのサポートが導入された。[http://www.foxprohistory.org/foxprotimeline.htm#summary_of_fox_releases Summary of Fox releases]</ref><ref>FoxProの歴史: [http://www.foxprohistory.org/tableofcontents.htm Foxprohistory.org]</ref><ref>1995年のVisual FoxPro 3.0 レビュー/ガイド: [http://www.dfpug.de/loseblattsammlung/migration/whitepapers/vfp_rg.htm DFpug.de]</ref>、[[C++]]<ref>{{Cite book|url=https://books.google.com/books?id=MHmqfSBTXsAC&pg=PA16|title=Object Oriented Programming with C++, 1E|isbn=978-81-259-2532-3|last1=Khurana|first1=Rohit|date=1 November 2009}}</ref>、[[Delphi]]<ref>マイナビTECH+: Delphiがトップ20位から脱落: 「Delphiは2001年6月にトップ20位入りを果たし、2000年代初頭には最も人気のある統合開発環境として広く使用されていた。」[https://news.mynavi.jp/techplus/article/20200306-988782/]</ref>などがある。 |
|||
:1962年に公開された[[Simula]]の後継版であり、[[クラス (コンピュータ)|クラス]]のプログラミング概念を導入した最初の言語である。現実世界の擬似モデルを観測するシミュレーション・プログラム制作用に開発されたもので、クラスを実メモリに展開したオブジェクトは、その観測対象要素となった。Simulaのクラスは、サブルーチンに専用変数と補助プロシージャを加えた機能的小型モジュールに近いものであったが、継承と仮想関数という先進的な設計を備えていた事でOOPの草分けと見なされるようになった。C++、Java、C#の設計母体となった。 |
|||
その勢力は、オブジェクト指向プログラミング技術に支えられた[[グラフィカルユーザインタフェース]]の人気向上と共に高まった。動的なGUIライブラリとOOP言語が密接に連携している例としては、Smalltalkを規範にしたCのオブジェクト指向の動的メッセージング拡張である[[Objective-C]]で書かれた[[macOS]]の[[Cocoa (API)|Cocoa]]フレームワークなどが挙げられる。また、OOPツールキットの存在は、[[イベント駆動型プログラミング]]の人気を高めることにも繋がった(ただし、この概念はOOPに限定されるものではない)。 |
|||
;[[Smalltalk]] 1972年 |
|||
[[チューリッヒ工科大学]]では、[[ニクラウス・ヴィルト]]らが、[[抽象化_(計算機科学)#データ抽象化|データ抽象化]]や{{仮リンク|モジュール化プログラミング|en|Modular programming}}などの研究を行っていた (ただし、これらは1960年代以前にも一般的に使われてはいた)。 |
|||
:[[メッセージパッシング]]のプログラミング概念を導入した最初の言語。数値、真偽値から変数、構造体、コードブロック、メタデータまでのあらゆる要素をオブジェクトとする概念を編み出した最初の言語でもある。オブジェクト指向という言葉は、Smalltalk開発者がその言語設計を説明する中で生み出された。オブジェクトの基礎的な振る舞いを規定する限られた予約語の他は、オブジェクトとメッセージのやり取りで制御構造を含めたあらゆるプロセスを表現出来た。また、専用のランタイム環境上でプログラムを実行する設計を応用して動的な多態性とセキュリティに繋がるモニタリングも実現した。これは後に仮想マシンと呼ばれるものとなり、JavaやC#に踏襲された。 |
|||
1978年に発表された[[Modula-2]]にはこの2つが盛り込まれており、その後に発表された[[Oberon]]では、オブジェクト指向やクラスなどに対する独自のアプローチが盛り込まれている<ref name=ETH>{{Cite report |last=Wirth |first=Niklaus |title=From Modula to Oberon and the programming language Oberon |series=ETH Technical Reports D-INFK |volume=Band 82 |publisher=Wiley |url=https://doi.org/10.3929/ethz-a-005363226}}</ref>。 |
|||
;[[C++]] 1983年 |
|||
:[[C言語]]にOOPデザインを追加したもの。Simulaの影響を受けている。[[クラス (コンピュータ)|クラス]]のメカニズムが備えられて、カプセル化、継承、多態性といったOOP仕様を実装している。[[テンプレート (プログラミング)|テンプレート機能]]や[[例外処理]]、演算子オーバーロードを応用した関数オブジェクトなど様々なプログラミングパラダイムも導入された。元がC言語であるため、OOPから逸脱したコーディングも多用できる点が物議を醸したが、その是非はプログラマ次第であるという結論に落ち着いた。 |
|||
;[[Objective-C]] 1984年 |
|||
:[[C言語]]をOOPデザイン化したもの。こちらはSmalltalkの影響を受けており、それに準じた[[メッセージパッシング]]と[[リフレクション (情報工学)|リフレクション]]のメカニズムが備えられた。OOP的には前述のC++よりも正統であると見なされた。制御構文が追加され、メッセージの仕様もやや簡素化されるなど実践上の便宜が図られており、Smalltalkよりもコーディングし易くなった。 |
|||
;[[Object Pascal]] 1986年 |
|||
:[[Pascal]]をOOPデザイン化したもの。 |
|||
;[[Eiffel]] 1986年 |
|||
:[[Pascal]]をベースにしてOOPデザイン化し、また[[ジェネリックプログラミング]]を追加した。型付けは静的に限られ、非参照データを自動解放する[[ガーベジコレクション|ガーベジコレクタ]]を持ち、多重継承時の問題を回避する仕組みや例外処理など高い堅牢性を備えた。これらは後のJavaやC#の手本となった。 |
|||
;[[Self]] 1987年 |
|||
:メッセージパッシングの構文が中心となっている。動的な多態性を重視した言語であり、従来の[[クラスベース]]のオブジェクト設計に対して、システム側が用意したオブジェクトを複製して任意の拡張を施す[[プロトタイプベース]]のデザインを初めて実装した。Smalltalkと同様に専用のランタイム環境で実行されたが、これも実用面では初となる[[実行時コンパイラ]](''just-in-time compiler'')の機能が備えられて速度面でも画期的なものとなった。 |
|||
;[[CLOS]] 1988年 |
|||
:[[Common Lisp]]をOOPデザイン化したもの。 |
|||
;[[Python]] 1990年 |
|||
:[[インタプリタ]]式で動作する。言語仕様を簡素化し自動メモリ管理機能を実装して扱いやすく理解しやすいOOPを目指している。後のOOPスクリプト言語の手本となった。 |
|||
;[[Java]] 1995年 |
|||
:堅牢性と安全性を重視したOOP言語。その二つの理念を実現するために、仮想マシン上の実行、ガーベジコレクタ、例外処理などを採用し、ポインタと直アドレス変数、多重継承、ジェネリックプログラミング、演算子オーバーロードなどを破棄した。破棄部分についてはその埋め合わせの設計も備えられた。[[クラス (コンピュータ)|クラス]]のメカニズムを中心にしたOOPであるが、様々なプログラミングパラダイムも追加されている。非常に整えられたハイブリッドOOP言語である。 |
|||
;[[Delphi]] 1995年 |
|||
:[[Object Pascal]]を発展させたもので、データベースの操作プログラム開発などを主な用途とした。一時期Javaの対抗馬となった。 |
|||
;[[Ruby]] 1995年 |
|||
:OOPデザインされたスクリプト言語である。[[インタプリタ]]式で動作する。スクリプトでありながら、クラス、マルチスレッド、例外処理、そして[[ソフトウェアコンポーネント]](モジュール)を扱える[[Mixin]]といった利便性の高い機能も備えている。 |
|||
;[[JavaScript]] 1996年 |
|||
:[[ウェブアプリケーション]]開発を主な目的とするOOPスクリプト言語。主に[[プロトタイプベース]]でオブジェクトを扱う事でコーディングを簡便にしている。[[ECMAScript]]として標準化されている。ECMAScript 2015ではクラス構文をサポートするようになった。 |
|||
;[[C Sharp|C#]] 2000年 |
|||
:[[Java]]を強く意識して開発されたOOP言語。[[.NET Framework]]などの[[共通言語基盤]]上で実行される。Javaと同等または部分的に拡張させたスタイルを持ち、こちらもよく整えられたハイブリッドOOP言語として知られる。 |
|||
;[[Microsoft Visual Basic .NET|Visual Basic.NET]] 2002年 |
|||
:[[Microsoft Visual Basic|Visual Basic]]をOOPデザイン化したもの。[[.NET Framework]]などの[[共通言語基盤]]上で実行される。 |
|||
;[[Ceylon]] 2011年 |
|||
:[[Java]]を元に開発され、その長所と短所を見直しつつ再設計されたOOP言語。Javaの改造版である。また[[JavaScript]]にもコンバートできる。 |
|||
;[[Kotlin]] 2011年 |
|||
:[[Javaバイトコード]]を出力し、[[Java仮想マシン]]上で動作するJavaテクノロジー互換OOP言語である。OOPでありながらグローバル関数および変数の使用も容認されており、オブジェクト指向プログラミングを手続き型プログラミングのスタイルに崩したかのようにデザインされている。 |
|||
;[[Swift (プログラミング言語)|Swift]] 2014年 |
|||
:高度に整えられたマルチパラダイムプログラミング言語。クラスのメカニズムをベースにしたオブジェクト指向プログラミングも導入されている。 |
|||
オブジェクト指向の機能は、[[Ada]]、[[BASIC]]、[[Fortran]]、[[Pascal]]、[[COBOL]]など、既存の多くの言語に追加されていったが、しかし、設計当初にこれらの機能を想定していなかった言語に追加した場合、コードの互換性や保守性には問題が生じることが多かった。 |
|||
== OOP言語の仕組み == |
|||
オブジェクト指向プログラミング言語は、相互に'''[[#メッセージ|メッセージ]]'''を送りあう'''[[オブジェクト (プログラミング)|オブジェクト]]'''の集まりとして[[プログラム (コンピュータ)|プログラム]]を構成することができる仕組みを持つ。 |
|||
そのために、少なくともオブジェクトについての3つの仕組みと、オブジェクトの管理についての3つの仕組みが必要となる。 |
|||
最近では、主としてオブジェクト指向でありながら、手続き型プログラミングの方法論にも対応した言語が数多く登場している。そのような言語としては、[[Python]]や[[Ruby]]がある。最近の商業的なオブジェクト指向言語で最も重要なものには、[[サン・マイクロシステムズ]]社が開発した[[Java]]や、Microsoftの[[.NET Framework|.NET]]プラットフォーム用に設計された[[C Sharp|C#]]、[[Visual Basic .NET]] (VB.NET) が挙げられる。 |
|||
;オブジェクトの仕組み |
|||
これら二つのフレームワークは、実装を抽象化することによるOOP使用の利点をそれぞれの方法で示している。VB.NETとC#間では言語間継承をサポートしており、一方の言語で定義されたクラスが他方の言語で定義されたクラスをサブクラス化することができる<ref>共通型システム|Microsoft Docs [https://docs.microsoft.com/ja-jp/dotnet/standard/base-types/common-type-system]</ref>。 |
|||
:* オブジェクトに蓄えられる情報、データを表現する仕組み。 |
|||
:* 他のオブジェクトにメッセージを配送する仕組み。 |
|||
:* 受け入れ可能な各種メッセージに対応して、処理する事柄を記述する仕組み([[メソッド (計算機科学)|メソッド]])。 |
|||
: |
|||
;オブジェクトを管理する仕組み |
|||
:* オブジェクト間の関係を整理分類して系統立てる仕組み。 |
|||
:* 必要なオブジェクトを作成・準備する仕組み。 |
|||
:* 不要なオブジェクトを安全に破棄する仕組み。 |
|||
== OOPLの特徴 == |
|||
これらをどのように言語の要素として提供し、どのような[[機械語]]コードで実現するかによって様々な[[オブジェクト指向プログラミング言語]]のバリエーションが生まれる。以下、オブジェクト指向プログラミング言語が提供する様々な要素が上記の仕組みをどのように実現しているかについて概観する。 |
|||
<!-- ここから [[en:Object-oriented programming]] oldid=1051733225 の翻訳 -->オブジェクト指向プログラミング言語 ('''OOPL''') では、オブジェクトを使用するが、言語仕様でOOP対応を謳っていても、関連する技術や構造のすべてが言語機能により直接サポートされているわけではない。以下に挙げる特徴は、特に言及されている例外を除いて、クラス指向やオブジェクト指向の傾向が強いとされる言語 (あるいはOOPをサポートする[[マルチパラダイムプログラミング言語]])に共通すると考えられるものである。<!-- ここまで [[en:Object-oriented programming]] oldid=1051733225 の翻訳 --> |
|||
=== 非OOPLとの共通点 ===<!-- ここから [[en:Object-oriented programming]] oldid=1051733225 の翻訳 --> |
|||
=== オブジェクトの概念と実装 === |
|||
; [[変数 (プログラミング)|変数]]: [[整数型]]や英数字の[[キャラクタ (コンピュータ)|文字]]のような形式化された少数の組み込み[[データ型]]の情報、または、[[文字列]]、[[リスト (抽象データ型)|リスト]]、[[ハッシュテーブル]]などの[[データ構造]]に、組み込み型もしくは、[[ポインタ (プログラミング)|ポインタ]]が格納されたものを結果として格納することができる。 |
|||
'''[[オブジェクト (プログラミング)|オブジェクト]]''' ({{Lang|en|object}}) はオブジェクト指向プログラミングの中心となる'''概念'''であり、この概念を'''実際'''にどう実現するかは[[オブジェクト指向プログラミング言語]]により異なる。 |
|||
; 手続き(関数、メソッド、[[サブルーチン]]とも呼ばれる): 入力を受け取り、出力を生成し、データを操作する。近年の言語には、[[制御構造#ループ|ループ]]や[[if文|条件構文]]のような[[構造化プログラミング]]の構成要素が含まれる。 |
|||
[[:en:Modular programming|モジュラープログラミング]]サポートでは、手続きをファイルやモジュールにまとめて整理する機能がある。モジュールは[[名前空間]]を持つため、あるモジュールの識別子が、他のモジュールの同名の手続きや変数と衝突することを避けることができる。<!-- ここまで [[en:Object-oriented programming]] oldid=1051733225 の翻訳 --> |
|||
以下、概念と実際がどう対応しているかについて説明する。 |
|||
=== クラスとオブジェクト === |
|||
* 概念的には各々のオブジェクトは、プログラムが表現する情報システムの中で能動的な役割を持った存在を表現している。 |
|||
<!-- ここから [[en:Object-oriented programming]] oldid=1051733225 の翻訳 -->オブジェクト指向プログラミング(OOP)をサポートする言語は、コードの再利用と拡張性のために、典型的には、[[クラスベース|クラス]]または[[プロトタイプベース|プロトタイプ]]の形で[[継承 (プログラミング)|継承]]を使用する。クラスを使用するものは、主に二つの概念をサポートする。 |
|||
* 概念的には '''メッセージ'''を受け取り、その処理の過程で内部に蓄えたデータを書き換え、必要に応じて他のオブジェクトにメッセージを送るといった動作をしている。 |
|||
; [[クラス (コンピュータ)|クラス]] |
|||
* 概念的には コードとデータが一つになっている。 |
|||
: 与えられた型やクラスのオブジェクトのデータ形式やそれらを利用可能な手続きの定義であり、また、データや手続き (クラスメソッドとも呼ばれる)そのものを含む場合もある。つまり、クラスは、メンバーとなるデータや手続きを含むものである。 |
|||
; [[オブジェクト (プログラミング)|オブジェクト]] |
|||
: クラスのインスタンス |
|||
<!-- ここまで [[en:Object-oriented programming]] oldid=1051733225 の翻訳 --> |
|||
<!-- ここから [[en:Object-oriented programming]] oldid=1051733225 の翻訳 -->オブジェクトは、システムが扱おうとする(多くは現実世界の)対象を表現したものである。例えば、描画アプリケーションにおける「円」・「四角」・「メニュー」などのオブジェクトや、オンラインショッピングシステムにおける「ショッピングカート」・「顧客」・「商品」などのオブジェクトがある<ref>{{cite book|last=Booch|first=Grady|title=Software Engineering with Ada|year=1986|publisher=Addison Wesley|isbn=978-0-8053-0608-8|page=220|url=https://en.wikiquote.org/wiki/Grady_Booch|quote=Perhaps the greatest strength of an object-oriented approach to development is that it offers a mechanism that captures a model of the real world.}}</ref>。 |
|||
==== オブジェクトの実装構造 ==== |
|||
オブジェクトは、ファイルのオープンを表すオブジェクトや、[[米国慣用単位]]から[[メートル法]]に変換するサービスを提供するオブジェクトのように、より抽象的なエンティティを表すこともある。 |
|||
{{Quote box |
|||
例えば勤怠管理のシステムであれば、氏名や年齢、累積勤務時間などの'''データ'''は異なっても社員は皆、出勤し退勤するという処理('''振る舞い''')は同じだろう。このように複数の異なるオブジェクトが同じ種類のメッセージを受け取り共通の処理をするのが普通である。 |
|||
|quote = オブジェクト指向プログラミングとは、単なるクラスやオブジェクトではなく、データフィールドやメソッドを含んだオブジェクト (データ構造)を中心としたプログラミングパラダイム全般のことです。クラスを使って、関係のないメソッドをまとめて整理する——これがオブジェクト指向の本質ではないことを理解しましょう。 |
|||
|author = Junade Ali |
|||
|source = ''Mastering PHP Design Patterns''{{harv|Ali|2016|p=11}} |
|||
|width = 50% |
|||
|align = right |
|||
}} |
|||
各々のオブジェクトは、特定のクラスの[[インスタンス]]と呼ばれる (例えば、<code>name</code>フィールドに <code>"Mary"</code>が設定されているオブジェクトは、クラス<code>Employee</code>のインスタンスとなる)。OOPの手続きは[[メソッド (計算機科学)|メソッド]]と呼ばれ、変数は、[[フィールド (計算機科学)|フィールド]]、メンバー、属性、プロパティとも呼ばれる。関連して、以下のような用語がある |
|||
このような場合、各オブジェクトがそれぞれメッセージ処理のコード(前述の「振る舞い」に当たる)を独自に備えていては無駄である。そこでオブジェクト指向プログラミング言語がオブジェクトを実現する際には多くの場合、内部的にはオブジェクトを2つの部分に分けている。 |
|||
; [[クラス変数]] |
|||
: クラス自体に属する。変数をクラス全体に唯一のものとして所有する。 |
|||
; [[インスタンス変数]]または属性 |
|||
: 各々のオブジェクトに属する。データはオブジェクトごとに所有する。 |
|||
; [[メンバ変数]] |
|||
: 特定のクラスで定義されるクラス変数とインスタンス変数の両方を指す。 |
|||
; [[クラスメソッド]] |
|||
: クラス自体に属する。クラス変数へのアクセスのみ有し、手続き呼び出しからの入力のみ受け付ける。 |
|||
; [[インスタンスメソッド]] |
|||
: 各々のオブジェクトに対して、呼び出された特定のオブジェクトのインスタンス変数、入力、およびクラス変数にアクセスできる。 |
|||
オブジェクトは、複雑な内部構造を持った変数のようにアクセスされるが、多くの言語で実質的には[[ポインタ (プログラミング)|ポインタ]]でありインスタンス (ヒープやスタック内のメモリ上オブジェクト)への参照として機能する。オブジェクトは、内部コードと外部コードを分離を可能とする[[抽象化 (計算機科学)|抽象化]]の層を提供する。外部のコードは、特定の入力引数の組み合わせで特定のインスタンスメソッドを呼び出したり、インスタンス変数を読み込んだり、インスタンス変数に書き込んだりすることで、オブジェクトを使用することができる。オブジェクトは、[[コンストラクタ]]と呼ばれるクラス内の特定メソッドを呼び出すことで生成される。プログラムは実行中に、それぞれ独立して操作することが可能な同じクラスのインスタンスを多数作成することができる。これは、同じ手続きを異なるデータセットで簡便に利用する方法となる。 |
|||
; 同一種類のオブジェクトの間で変わらない共通部分 |
|||
: 一つは同一種類のオブジェクトに共有される部分、例えばメッセージ処理のコード(振る舞い)や定数(どのオブジェクトでも異ならないデータ)の類である。 |
|||
; 同一種類のオブジェクトの間で変わる個々の部分 |
|||
: もう一つは同一種類のオブジェクトでもそれぞれ異なる部分、典型的には各オブジェクトが保持するデータ群である。 |
|||
クラスを使用するOOPを[[クラスベース]]・プログラミングと呼ぶことがあるが、[[プロトタイプベース]]・プログラミングではクラスを使用しないのが一般的である。そのため、'''オブジェクト'''と'''インスタンス'''という概念の定義は、それぞれで大きく異なるが類似した用語が用いられている。 |
|||
==== クラスのオブジェクト化 ==== |
|||
動的型付けを採用するオブジェクト指向言語の多くは、クラスより生成するインスタンスの他に[[メタクラス]]という機能を持ちクラス自体をオブジェクトとして扱うことが出来る。このためオブジェクトには、インスタンスオブジェクトとクラスオブジェクトという2種類のオブジェクトが存在する。Java等クラスオブジェクトを持たない言語の文化圏では、インスタンスオブジェクトとオブジェクトを混同して説明される事があるが、Objective-CやPython、Ruby等、インスタンスオブジェクトとクラスオブジェクトが別であるオブジェクト指向言語では区別して説明される。<ref>Objective-Cプログラミ |
|||
ング言語[https://developer.apple.com/jp/devcenter/ios/library/documentation/ObjC.pdf]</ref> |
|||
<ref>Classes ― Python v2.7.3 documentation[http://docs.python.org/2/tutorial/classes.html]</ref> |
|||
<ref>クラス/メソッドの定義 (Ruby manual) [http://www.ruby-lang.org/ja/old-man/html/_A5AFA5E9A5B9A1BFA5E1A5BDA5C3A5C9A4CEC4EAB5C1.html]</ref>元々はSmalltalkから始まった用語である。 |
|||
言語によっては、[[トレイト]]や[[mixin]]のような概念を用いてクラスやオブジェクトを構成することが可能である。<!-- ここまで [[en:Object-oriented programming]] oldid=1051733225 の翻訳 --> |
|||
==== thisデータの扱い方 ==== |
|||
{{seealso|this (プログラミング)}} |
|||
そしてあるオブジェクトOにメッセージを配送し適切なメッセージ処理コード(振る舞い)を呼び出す際には、まず対象となるオブジェクトOについて共通部分の格納場所を見つけて適切なコードを選び出し、次にそのコードに対して処理対象となるオブジェクトO固有のデータの所在を示す'''オブジェクトID'''を渡すようになっている。 |
|||
=== クラスベース対プロトタイプベース === |
|||
各オブジェクトの固有データを識別するオブジェクトIDを表現する方法も様々で、オブジェクトのIDとしては名前、番号なども用いられることがあるが、オブジェクトの固有データを記憶している[[主記憶]]上の[[メモリアドレス|アドレス]]がそのまま用いられることもある。アドレスを直接利用することは非常に実行効率の向上に寄与するが、プログラム間でのオブジェクトの受け渡し、セッション間(プログラムが終了して再度起動された時など)でのオブジェクトの受け渡しにはそのまま利用することができない。 |
|||
<!-- ここから [[en:Object-oriented programming]] oldid=1051733225 の翻訳 -->[[クラスベース|クラスベースの言語]]では、予め''クラス''が定義され、そのクラスに基づいて''オブジェクト''がインスタンス化される。例えば、''apple''と''orange''という2つのオブジェクトが、''Fruit''というクラスからインスタンス化された場合、それらは本質的には果物であり、同じように取り扱えることの保証がされる。 |
|||
[[プロトタイプベース|プロトタイプベースの言語]]では、''オブジェクト''が主要な実体である。''クラス''は存在しない。オブジェクトの''プロトタイプ''とは、あるオブジェクトからリンクされている別のオブジェクトに過ぎない。すべてのオブジェクトは一つの''プロトタイプ''リンクを持つ (一つのみ)。新しいオブジェクトは、プロトタイプとして選ばれた既存のオブジェクトに基づいて作成することができる。''fruit''オブジェクトが存在し、''apple''と''orange''の両方が''fruit''をプロトタイプとしている場合、2つの異なるオブジェクト''apple''と''orange''を果物と考えることができる。''fruit''「クラス」という概念は明示的には存在しないが、同じプロトタイプを共有するオブジェクトの[[同値類|同値クラス]]としては存在する。''プロトタイプ''の属性やメソッドは、このプロトタイプで定義された同値クラスのすべてのオブジェクトから[[委譲]]先とされる。オブジェクト固有の属性やメソッドは、同値クラスの他のオブジェクトに共有されない場合がある。例えば、属性''sugar_content''は''apple''には予期せず存在しない場合がある。プロトタイプで実装できるのは[[:en:Multiple_inheritance#Single_inheritance|単一継承]]のみである。<!-- ここまで [[en:Object-oriented programming]] oldid=1051733225 の翻訳 --> |
|||
また各オブジェクトの固有データから共通部分の格納場所を見つける方法もまた各言語により異なり、その言語の開発目的に応じて実に多種多様である。 |
|||
=== 動的ディスパッチとメッセージパッシング === |
|||
; JavaScriptの場合 |
|||
<!-- ここから [[en:Object-oriented programming]] oldid=1051733225 の翻訳 --> |
|||
: 例えば[[JavaScript]]の場合、各オブジェクトは[[連想配列]]であり、名前で表現されたメッセージのIDからメッセージ処理コードである関数への参照を直接見つけ出す。各オブジェクトの固有データもその連想配列に格納されていて、メッセージを処理する関数には連想配列のアドレスが渡される。 |
|||
メソッドの呼び出しに応じて実行する手続きのコードを選択するのは、外在するコードではなく、オブジェクトの責任である。典型的には、オブジェクトに関連付けられたテーブルから実行時にメソッドを検索するが、この機能は[[:en:Dynamic dispatch|動的ディスパッチ]]として知られており、[[抽象データ型]] (またはモジュール)において、すべてのインスタンスの操作が静的に実装されているのとは対照的である。呼び出しの変化が、呼び出されたオブジェクトの単一の型にのみには依らない場合 (つまり複数のオブジェクトがメソッド選択に関与する場合)、[[多重ディスパッチ]]と呼ばれる。 |
|||
; Selfの場合 |
|||
: [[Self]]のような[[プロトタイプベース|インスタンスベース]]のオブジェクト指向プログラミング言語では、プロトタイプとなるオブジェクトがメッセージを処理するコードも保持しており、オブジェクトがクローンされて作成されるときにそのプロトタイプのありかを示す情報もコピーされ、メッセージは受け取ったオブジェクトのIDを添えてプロトタイプに送られて処理される(Selfでは実行効率上の問題から後に内部的にクラスを作って利用するようになっている)。 |
|||
; クラスベースの言語の場合 |
|||
: 最も普及している[[クラスベース]]の言語では、共通部分はオブジェクトの種類を表現するクラスに保持され、各オブジェクトは固有データと共にそのクラスのIDを保持する。そしてオブジェクトに送られるメッセージはその送り先オブジェクトにあるクラスのIDからクラスを見つけ、その中からメッセージを処理するコードを見つけ出し、処理対象となっているオブジェクトのIDを付してそのコードを呼び出す仕組みになっている。 |
|||
メソッド呼び出しは、[[メッセージ (コンピュータ)|メッセージパッシング]]とも呼ばれる。これは、メソッド呼び出しを、ディスパッチのためにオブジェクトに渡されるメッセージ (メソッドの名前とその入力引数)として概念化したものである。<!-- ここまで [[en:Object-oriented programming]] oldid=1051733225 の翻訳 --> |
|||
==== コンポジション ==== |
|||
'''コンポジション'''は、複数のオブジェクトがある一つのオブジェクトの構成要素となっている巨大なオブジェクト群をいう。コンポジションのもとにあるオブジェクトは同一の生存期間を持ち、一つの巨大な仮想オブジェクトの構成部品として機能する。 |
|||
=== |
=== カプセル化 === |
||
<!-- ここから [[en:Object-oriented programming]] oldid=1051733225 の翻訳 -->[[カプセル化]]とは、オブジェクト指向プログラミングにおいて、データとそのデータを操作する関数を結び付け、両者を外部からの干渉や誤用から守ることである。データのカプセル化は、OOPの重要な概念である{{仮リンク|情報隠蔽|en|Information hiding|redirect=1}}にも通じる。 |
|||
'''メッセージ''' ({{Lang|en|message}}) はオブジェクト間の通信でやりとりされる情報である。メッセージはメッセージ種別を示すIDとメッセージの種別に応じた追加の情報からなる定まった形式を持つ。追加の情報はそれ自身が何らかのオブジェクトや[[オブジェクトのID]]である場合もある。メッセージの配送には大別して2つの方式がある: |
|||
クラスがメソッドを通じてのみオブジェクトの内部データへのアクセスを許可し、それ以外の呼び出しコードにアクセスを許可しない場合、これはカプセル化として知られる強力な抽象化、または情報隠蔽の形態である。いくつかの言語 (Javaなど)では、クラスがアクセス制限を明示的に行うことができる。例えば、内部データであることを<code>private</code>というキーワードで指定し、クラス外のコードが使用することを意図したメソッドを<code>public</code>というキーワードで指定することができる。また、メソッドはpublic、private、または<code>protected</code> (同クラスとそのサブクラスからのアクセスは許可するが、異なるクラスのオブジェクトからのアクセスは許可しない)のように中間のアクセスレベルとすることもできる。また他の言語 (Pythonなど)では、アクセス制限は、命名法などの慣例によってのみ強制される (例えば、<code>private</code>のメソッドは[[アンダースコア]]で始まる名前を持つ、など)。カプセル化することで、外部のコードがオブジェクトの内部動作に関与してしまうことを防ぐことができ、[[リファクタリング (プログラミング)|リファクタリング]]を容易にする。例えば、クラスの設計者は、外部のコードは変更することなく、そのクラスのオブジェクト内部のデータ表現を変更することができる (公開されているメソッドの呼び出しが同じように動作する限りにおいて)。また、特定のデータに関連するすべてのコードを同じクラスに配置することで、他のプログラマが理解しやすいように整理することもできる。カプセル化は、[[結合度|疎結合]]を促進する技術である。<!-- ここまで [[en:Object-oriented programming]] oldid=1051733225 の翻訳 --> |
|||
; 同期式 |
|||
: オブジェクトがメッセージの送信を依頼すると相手が受信、処理して結果を返すまでそのオブジェクトは処理を中断して待つ。 |
|||
; 非同期式 |
|||
: オブジェクトがメッセージの送信を依頼した後、相手の応答を待たずにオブジェクトは処理を続行する。処理結果は別のメッセージとして返される。 |
|||
=== コンポジション、継承、委譲 === |
|||
両者とも一長一短がありどちらがすぐれているとは言えない。また並列・並行処理が可能な環境では一方の仕組みがあれば、それを利用してもう一方も実現可能である。一般的な傾向としては、メッセージの伝送や処理に時間が掛かる場合は非同期式の方が効率は良く、そうでない場合には同期式の方が挙動が分かりやすく利用しやすい。 |
|||
<!-- ここから [[en:Object-oriented programming]] oldid=1051733225 の翻訳 -->オブジェクトは、そのインスタンス変数に他のオブジェクトを含めることができ、これを[[:en:object composition|オブジェクトコンポジション]]と呼ぶ。例えば、"従業員"クラスのオブジェクトは、"名前" や "役職"といった自身のインスタンス変数に加えて、"住所"クラスのオブジェクトを (直接またはポインタを介して)含むことができる。 |
|||
オブジェクトコンポジションは、"has-a" の関係を表現するために使用できる。例えば、すべての従業員は住所を持っているので、すべての"従業員"オブジェクトは、"住所"オブジェクトを格納する場所 (オブジェクトに直接埋め込まれていることも、ポインターで指定された別の場所に格納されることもある)にアクセスできる。<!-- ここまで [[en:Object-oriented programming]] oldid=1051733225 の翻訳 --> |
|||
<!-- ここから [[en:Object-oriented programming]] oldid=1051733225 の翻訳 -->クラスをサポートする言語は、大抵は[[継承 (プログラミング)|継承]]をサポートしている。継承とは、クラスを「○○は△△である」という関係("is-a-type-of")の階層に配置することであるが、例えば、<code>Employee</code> クラスは <code>Person</code> クラスを継承する場合、親クラスで利用できるデータやメソッドは、子クラスでも同じ名前で利用可能である。また、<code>Person</code> クラスは、<code>first_name</code> と <code>last_name</code> という変数を <code>make_full_name()</code> というメソッドで定義した場合、これらの定義は<code>Employee</code>クラスでも利用可能である。加えて、<code>Employee</code>クラスには変数 <code>position</code> と <code>salary</code> を追加することもできる。この手法では、同じ手続きやデータ定義を簡単に再利用できるだけでなく、現実世界の関係を直感的に反映できる可能性を広げる。開発者は、データベースのテーブルやプログラミングのサブルーチンを扱うのではなく、開発アプリケーションのユーザーがより精通しているドメインのオブジェクトを扱うことができる<ref>{{cite book|last=Jacobsen|first=Ivar|title=Object Oriented Software Engineering|year=1992|publisher=Addison-Wesley ACM Press|isbn=978-0-201-54435-0|pages=[https://archive.org/details/objectorientedso00jaco/page/43 43–69]|author2=Magnus Christerson|author3=Patrik Jonsson|author4=Gunnar Overgaard|url=https://archive.org/details/objectorientedso00jaco/page/43}}</ref>。<!-- ここまで [[en:Object-oriented programming]] oldid=1051733225 の翻訳 --> |
|||
[[並列処理]]・[[並行処理]]システムを記述する言語や[[分散コンピューティング|分散システム]]を記述する言語ではOSなどが提供するメッセージ機能や自前の配送メカニズムを使って非同期式でメッセージが配送される場合もあるが、一般にオブジェクト指向プログラミング言語ではその多くが同一のプログラム内の通信であるので同期式のメッセージ配送が利用される。特に[[コンパイル]]されるタイプのオブジェクト指向プログラミング言語では、しばしば特別なメッセージ配送の仕組みを用意せず、特別な形式の関数の呼び出しでメッセージの配送を直接に表現する。即ち、各メソッドを内部的には関数として実現し、メッセージIDはメソッド名で表し、関数の第一引数としてオブジェクトIDを渡し(この第一引数は多くの言語で特別な記法で表される)、追加の引数としてメッセージの追加部分の情報を渡すのである。こうするとメッセージ送信は直接的なメソッドの関数呼び出しとして表せる。ただし、プログラムで[[継承 (プログラミング)|継承]]の仕組みが利用されている場合はプログラムのテキストからだけでは呼び出すべきメソッドが決定できない場合があるので、実行時にメソッドを決定するために[[メソッド・サーチ]]や[[仮想関数テーブル]]といった仕組みが必要となる。 |
|||
<!-- ここから [[en:Object-oriented programming]] oldid=1051733225 の翻訳 -->サブクラスはスーパークラスで定義されたメソッドをオーバーライドできる。言語よっては[[:en:Multiple inheritance|多重継承]]が可能だが、多重継承ではオーバーライドの解決は複雑になる可能性がある。また、言語によっては[[mixin]]を特別にサポートしているものもあるが、多重継承をサポートする言語では、mixinは単に ''is-a-type-of'' の関係を表すことのないクラスの一つである。mixinは典型的には、同一のメソッドを複数のクラスに追加するために使われる。例えば、共通の親クラスを持たない<code>FileReader</code>クラスと<code>WebPageScraper</code>クラスに、<code>unicode_to_ascii()</code>というメソッドを持つ<code>UnicodeConversionMixin</code>クラスを含ませる(mixinする)ことにより共通のメソッドを提供することができる。<!-- ここまで [[en:Object-oriented programming]] oldid=1051733225 の翻訳 --> |
|||
多くのプログラミング言語においてメッセージは、メソッド呼び出しの比喩でしかないことが多い。SmalltalkやObjective-Cの様な言語では、メッセージはメソッド呼び出しとは独立した機構として存在している。メッセージが機構として存在する言語では、メッセージをオブジェクトに送信した際、宛先のオブジェクトにメッセージで指定したメソッドが存在しない場合でもメッセージを処理することが出来る。これを利用し、メッセージの配送先を別のオブジェクトに指定したり、メッセージを一時保存したり、不要なメッセージを無視する等といったメッセージ処理が行われる。 |
|||
<!-- ここから [[en:Object-oriented programming]] oldid=1055370410 の翻訳 -->[[抽象型|抽象クラス]]は、オブジェクトへインスタンス化することはできない。インスタンス化できる他の具象クラスが継承するためにのみ存在する。Javaでは、<code>[[final (Java)|final]]</code>キーワードを用いて、クラスがサブクラス化されるのを防止できる。 |
|||
{{seealso|メッセージ転送}} |
|||
[[:en:Composition over inheritance|Composition over inheritance]]の方針は、継承の代わりに合成を使って has-a 関係を実装することを提唱している。例えば、EmployeeクラスはPersonクラスを継承する代わりに、各Employeeオブジェクトの内部にPersonオブジェクトを含めることで、仮にPersonクラスが公開された属性やメソッドを多数持っていても、外部のコードからは隠せるようにする。また、[[Go (プログラミング言語)|Go]]のように、継承を全くサポートしていない言語も存在する。 |
|||
=== クラス === |
|||
{{main|クラス (コンピュータ)}} |
|||
==== クラスベース ==== |
|||
'''クラス''' (class) は大多数のオブジェクト指向プログラミング言語で提供されている仕組みであり、上記の機能のほとんど全てに関わりがある。概念的にはクラスはオブジェクトの種類を表す。このためオブジェクトはクラスに'''属する'''という言い方をする。あるクラスに属するオブジェクトのことをそのクラスの'''インスタンス''' (instance) と呼ぶ。[[データ型]]の理論から見た場合クラスは型を定義する手段の一つである。クラスによってオブジェクトを記述する言語を'''[[クラスベース]]''' ({{Lang|en|class-based}}) のオブジェクト指向プログラミング言語と呼ぶ。 |
|||
[[開放/閉鎖原則]]は、クラスやメソッドは「拡張に対しては開放的であるが、変更に対しては閉鎖的であるべき」という原則を提唱している。 |
|||
ハイブリッド型オブジェクト指向プログラミング言語では在来の[[データ型#レコード型|レコード型]](Cでは[[構造体]])の構文を拡張してクラスの定義を行うようにしたものが多い。 |
|||
[[委譲]]もまた、継承の代わりに利用できる言語機能である。<!-- ここまで [[en:Object-oriented programming]] oldid=1055370410 の翻訳 --> |
|||
多くのオブジェクト指向プログラミング言語ではクラスを'''[[#データ・メンバ|データメンバ]]'''と'''[[#メソッド|メソッド]]'''の集まりとして記述する。平たく言えばデータ・メンバの集まりはオブジェクトが保持するデータの形式を定め、各メソッドはそれぞれオブジェクトが処理する特定のメッセージの処理方法を定める。しばしばデータ・メンバとメソッドには個別に[[オブジェクト指向プログラミング#アクセス権|アクセス権]]が設定できるようになっていて、そのクラスに属するオブジェクトが内部的に利用するものと他のクラスに属するオブジェクトに公開するものを分類できるようになっている。多くの場合、公開されたメソッドの集まりは全体として処理可能なメッセージのカタログの機能、即ち[[インタフェース (情報技術)|インタフェース]]を提供する。各言語によって異なるが特定の名前のメソッドを定めて、オブジェクトの生成や初期化時の処理、廃棄時の処理などを記述できるようにすることも多い。 |
|||
=== ポリモーフィズム === |
|||
多くの言語でクラスは言語の要素として直接実現されているが、これは実行効率のためであり、そのように実現することが必須というわけではない。実際、各クラスをそれぞれオブジェクトとして提供する言語も存在する(例:[[Smalltalk]])。このような言語ではある種の'''[[リフレクション (情報工学)|リフレクション]]''' (reflection) が可能となる。即ち必要があればプログラムで実行時にクラスの動作を変更することが可能である。これは非常に大きな柔軟性を提供するが、[[処理系|言語処理系]]による最適化が難しいため実行効率は低下することが多い。{{いつ範囲|date=2019年2月|近年}}では柔軟性と効率性を両立させるために基本的に言語要素としてクラスを提供した上で、リフレクション機能が必要なプログラムに対しては必要に応じて各クラスに対応するクラス・オブジェクトをプログラムが獲得できるようにしている言語が現れてきている。(例:JavaのリフレクションAPI) |
|||
<!-- ここから [[en:Object-oriented programming]] oldid=1051733225 の翻訳 -->[[サブタイピング (計算機科学)|サブタイピング]] ([[ポリモーフィズム]]の一形態)では、呼び出すコードが、サポートされている階層のどのクラスを操作しているのか (親クラスなのかその子孫なのか)という詳細には関知しないことが可能である。一方、継承階層内のオブジェクト間では、同じ操作名でも挙動が異なる場合がある。 |
|||
例えば、Circle型とSquare型のオブジェクトが、Shapeという共通のクラスから派生している場合、Shapeの各型のDraw関数は、それぞれの描画に必要な機能を実装しているが、呼び出しのコードは、描画されるShapeが特定の型であるかどうかには無関心でいられる。 |
|||
==== プロトタイプベース ==== |
|||
{{main|プロトタイプベース}} |
|||
クラスは非常に多くのオブジェクト指向プログラミング言語で提供されている機能ではあるが、オブジェクト指向プログラミング言語に必須の機能というわけではない。実際にオブジェクトの管理や、データ・メンバや[[メソッド (計算機科学)|メソッド]]の記述、[[継承 (プログラミング)|継承]]に際してクラスという仕組みに依存せずに、もしくはクラスという仕組み自体を持たずに別の手段でこれらを実現している言語も存在する。このような言語を'''[[プロトタイプベース|インスタンスベース]]''' (''{{Lang|en|instance-based}}'')、'''オブジェクトベース''' (''object-based'') あるいは'''プロトタイプベース''' (''{{Lang|en|prototype-based}}'') のオブジェクト指向プログラミング言語と呼ぶ。インスタンスベースまたはそれに類するオブジェクト指向プログラミング言語には以下のようなものがある: |
|||
これもまた、クラス階層からコードを引き離して単純化し、強力な[[関心の分離]]を可能にする抽象化の一種である。<!-- ここまで [[en:Object-oriented programming]] oldid=1051733225 の翻訳 --> |
|||
*[[Self]] |
|||
*[[JavaScript]] |
|||
*[[NewtonScript]] |
|||
*[[ドリトル (プログラミング言語)|ドリトル]] |
|||
* Squeak [[Etoys|eToys]]([[Squeak]]の非開発者向けビジュアルスクリプト言語。SqueakToys とも) |
|||
=== オープンな再帰 === <!-- ここから [[en:Object-oriented programming]] oldid=1051733225 の翻訳 --> |
|||
なお、クラスベースの言語とインスタンス・ベースの言語との間には明確な境界線はない。たとえば、インスタンス・ベースの代表格ともいえる Self には、traits と呼ばれるクラスのような仕組みが追加されているし、JavaScript、NewtonScript に至っては traits 類似の仕組みを「クラス」と呼称している。また逆に、クラスベースの言語でもクローンを行うメソッドを備え、委譲の仕組みを記述すればある程度はインスタンス・ベースのスタイルでプログラムを記述できる。 |
|||
[[:en:This_(computer_programming)#Open_recursion|オープンな再帰]]<ref>{{Cite book|和書|title=型システム入門 |publisher=オーム社 |year=2013 |page=185}} 18.10 selfを介したオープンな再帰</ref>をサポートする言語では、オブジェクトのメソッドは同じオブジェクト上の他のメソッドや自分自身を呼び出すことができる。通常は<code>this</code>や<code>self</code>と呼ばれる特別な変数やキーワードを使用して呼び出しをするのが一般的であるが、この変数は「[[束縛_(コンピュータ)#名前束縛|遅延結合]]」であり、あるクラスで定義されたメソッドが、そのサブクラスで後から定義された別のメソッドを呼び出すことができる。<!-- ここまで [[en:Object-oriented programming]] oldid=1051733225 の翻訳 --> |
|||
== デザインパターン == |
|||
インスタンス・ベースの言語ではオブジェクトの生成は既存のオブジェクト、特に'''プロトタイプ'''({{Lang|en|prototype}}、原型)と呼ばれるオブジェクトからのクローンによって行われる。当然、一群のクローンはその親、ひいてはプロトタイプと同一の種類のオブジェクトと見なされる。メソッドはプロトタイプ・オブジェクトに属し、メッセージは委譲によってそのオブジェクトが覚えているコピー元へ向かってプロトタイプまで順にメッセージが中継されてから処理される。新しい種類のオブジェクトが必要な場合は適当なオブジェクトをクローンした後で必要なデータ・メンバやメソッドを追加あるいは削除し新たなプロトタイプとすることで行われる。追加されたのでないメソッドに対応するメッセージについてはコピー元のオブジェクトに処理を委譲する。 |
|||
=== 継承とBehavioral subtyping === |
|||
クラスベースの言語との関係について考えてみると、クローンはプロトタイプと同一の「クラス」に属すると見なし、データ・メンバやメソッドが追加・削除されてあらたなプロトタイプが作られると別の「クラス」が内部的に生成されると考えることができる。ここでデータ・メンバやメソッドの追加のみを許して削除を許さないよう制限すればクローンの「クラス」がその親の「クラス」を継承した場合と同等になる。このためメッセージが委譲の連鎖をたどって配送されるという効率上の問題を無視すれば理論上、インスタンス・ベースの言語の記述能力はクラス・ベースの言語を包含していると言える。ただ、インスタンス・ベースの言語でも実行効率上の問題からなんらかのクラスに似た仕組みを備えている場合が多い。 |
|||
<!-- ここから [[en:Object-oriented programming]] oldid=1057169575 の翻訳 -->継承は[[プログラム意味論|意味論]]的には [[is-a]] の関係を作るため、サブクラスからインスタンス化されたオブジェクトは、スーパークラスからインスタンス化されたオブジェクトの代わりに、常に''安全に''使用できる、と推測するのは直感的ではあるが、この直観は、ほとんどのOOPL、特に[[イミュータブル|ミュータブル]]なオブジェクトを許可している言語では誤りである。 (ミュータブルなオブジェクトを持つ)OOPLの型検査器によって強制される[[ポリモーフィズム|部分型付け (部分型多相/サブタイピング多相)]]では、いかなる状況でも、振る舞いにおける部分型付け ([[:en:Behavioral subtyping|Behavioral subtyping]]) は保証することはできない。 Behavioral subtyping は一般に決定不能であり、プログラム (コンパイラ)では実装できない。クラスやオブジェクトの階層は、文法間違いでは検出できない使い方がされる可能性を考慮に入れて、慎重に設計する必要がある。この問題は[[リスコフの置換原則]]としても知られている。<!-- ここまで [[en:Object-oriented programming]] oldid=1057169575 の翻訳 --> |
|||
=== デ |
=== GoFデザインパターン === |
||
{{Main|デザインパターン (ソフトウェア)}} |
|||
'''データメンバ''' ({{Lang|en|data member}}) は、他のオブジェクトに対する[[参照 (情報工学)|参照]]や[[ポインタ (プログラミング)|ポインタ]]であるか、他のオブジェクトそのものである。参照かポインタである場合にはそのデータメンバの参照するのはデータメンバが記述されているクラスそのもののインスタンスに対する参照であっても良い。 |
|||
=== オブジェクト指向とデータベース === |
|||
一般にデータメンバは'''インスタンスデータメンバ'''('''[[インスタンス変数|インスタンスフィールド]]''')と'''クラスデータメンバ'''('''静的変数''')の2種類に大別できる。効率上の観点から言語が提供する基本オブジェクトの定数を表すデータメンバは特別扱いされる。そのような定数を表すデータメンバを特に'''定数データメンバ''' ({{Lang|en|constant data member}}) と呼ぶ。データメンバは[[C++]]などの言語では'''メンバ変数''' ({{Lang|en|member variable}})、[[Java]]などでは'''フィールド'''と呼ばれることがあり、[[統一モデリング言語|UML]]では[[属性]]と呼ばれる。 |
|||
<!-- ここから [[en:Object-oriented programming]] oldid=1057169575 の翻訳 --> |
|||
{{Main|[[インピーダンスミスマッチ|オブジェクト-リレーションインピーダンスミスマッチ]]|オブジェクト関係マッピング|オブジェクトデータベース}} |
|||
OOPL と[[関係データベース管理システム]] (RDBMS) は、どちらも{{As of|2021|alt=今日}}のソフトウェアとして非常に一般的であるが、双方を接続する場合、[[関係データベース]]は、オブジェクトを直接格納しないため (ただし、今日ではこれに近しい拡張機能を持つ RDBMS も存在する)、この二つの世界を橋渡しすることが一般的な需要として擡頭した。アクセス方法やデータパターンを OOPL と RDB との間で橋渡しする際の問題は、オブジェクト-リレーションの[[インピーダンスミスマッチ]]と呼ばれている。 |
|||
==== インスタンスデータメンバ ==== |
|||
この問題に対処するためのアプローチはいくつかある。欠点のない一般的な解決策といえるものはない<ref name="RDMDBobjectmis">{{Cite web| first = Ted| last = Neward| title = The Vietnam of Computer Science| date = 26 June 2006| access-date = 2 June 2010| publisher = Interoperability Happens| url = http://blogs.tedneward.com/2006/06/26/The+Vietnam+Of+Computer+Science.aspx| archive-url = https://web.archive.org/web/20060704030226/http://blogs.tedneward.com/2006/06/26/The+Vietnam+Of+Computer+Science.aspx| archive-date = 4 July 2006| url-status = dead| df = dmy-all}}</ref>が、代表的なものとして、[[オブジェクト関係マッピング]](ORM)があり、[[Microsoft Visual FoxPro|Visual FoxPro]]などの[[統合開発環境|IDE]]言語や、Java Data Objects、[[Ruby on Rails]]の[[Active Record]]などのライブラリが存在する。 |
|||
{{main|インスタンス変数}} |
|||
インスタンスデータメンバ(一般に単にデータメンバと言われる場合はこちら)はそのクラスのインスタンス各々に保持される。インスタンスデータメンバの集まりはそのクラスのインスタンスが保持するデータの形式を定める。インスタンスデータメンバは単にデータメンバと呼ばれることも多い。 |
|||
また、RDBMS を代替する[[オブジェクトデータベース]]も存在するが、技術的にも商業的にも RDBMS ほど広く成功は収めていない。<!-- ここまで [[en:Object-oriented programming]] oldid=1057169575 の翻訳 --> |
|||
[[Smalltalk]]では'''[[インスタンス変数]]''' ({{Lang|en|instance variable}}) と呼ばれる。 |
|||
=== OOPと制御構造 === |
|||
<!-- ここから [[en:Object-oriented programming]] oldid=1055370410 の翻訳 -->OOPは、ソースコードの[[コードの再利用|コードの再利用性]]や[[ソフトウェア保守|ソフトウェアの保守性]]を高めるよう発展してきたが<ref name="realisticcodereuse">{{Cite web| first = Scott| last= Ambler| title = A Realistic Look at Object-Oriented Reuse| date=1 January 1998| access-date=4 July 2010| publisher = drdobbs.com| url=http://www.drdobbs.com/184415594}}</ref> 、ある時期までは[[制御構造|制御フロー]]の透過的な表現については、あまり省みられることもなく、コンパイラが任意に処理すれば良いと考えられてきた。しかし、OOPでの実現にはある種の困難を伴うものの、並列ハードウェアや[[スレッド (コンピュータ)|マルチスレッドコーディング]]の重要性が増すにつれ透過的な制御フローの開発は重要になってきている<ref name="flaws">{{Cite web| first = Asaf| last= Shelly |title = Flaws of Object Oriented Modeling| date=22 August 2008|access-date=4 July 2010| publisher = Intel Software Network| url=http://software.intel.com/en-us/blogs/2008/08/22/flaws-of-object-oriented-modeling/}}</ref><ref name="multithreadingisaverb">{{Cite web| first = Justin| last = James| title = Multithreading is a verb not a noun| date = 1 October 2007| access-date = 4 July 2010| publisher = techrepublic.com| url = http://blogs.techrepublic.com.com/programming-and-development/?p=518| archive-url = https://web.archive.org/web/20071010105117/http://blogs.techrepublic.com.com/programming-and-development/?p=518| archive-date = 10 October 2007| url-status = dead| df = dmy-all}}</ref><ref name="multicore">{{Cite web| first = Asaf| last= Shelly| title = HOW TO: Multicore Programming (Multiprocessing) Visual C++ Class Design Guidelines, Member Functions| date=22 August 2008| access-date=4 July 2010| publisher = support.microsoft.com| url=http://support.microsoft.com/?scid=kb%3Ben-us%3B558117}}</ref><ref>{{cite web|url=http://existentialtype.wordpress.com/2011/04/17/some-advice-on-teaching-fp/|title=Some thoughts on teaching FP|author=Robert Harper |publisher=Existential Type Blog|access-date=5 December 2011|date=17 April 2011|author-link=Robert Harper (computer scientist)}}</ref>。<!-- ここまで [[en:Object-oriented programming]] oldid=1055370410 の翻訳 --> |
|||
{{main|クラス変数}} |
|||
クラスデータメンバはそのクラスオブジェクトとインスタンスオブジェクトの間で共有されるデータである。 |
|||
=== 責任駆動設計 対 データ駆動設計 === |
|||
[[Smalltalk]]ではクラスデータメンバは'''[[クラス変数]]''' ({{Lang|en|class variable}}) と呼ばれる。また、[[C++]]・[[Java]]では歴史的事情によりクラスデータメンバは'''静的データメンバ''' ({{Lang|en|static data member}})、'''静的変数''' (static variable)、'''静的フィールド''' ({{Lang|en|static field}}) と呼ばれる。 |
|||
<!-- ここから [[en:Object-oriented programming]] oldid=1057169575 の翻訳 -->[[:en:Responsibility-driven design|責任駆動設計]]では、クラスは、共有する情報とそれを扱う責務という観点から定義されるべきであるとし、クラス定義 (とその利用者)の契約として設計する。Wirfs-BrockとWilkersonは、責任駆動設計と対比して、[[:en:Data-driven programming|データ駆動設計]]は、クラスが保持すべきデータ構造のみを中心に定義されるとし、責任駆動型の設計が望ましいとしている<ref name="Wirfs-Brock1989">{{cite journal|last1=Wirfs-Brock|first1=Rebecca|last2=Wilkerson|first2=Brian|title=Object-Oriented Design: A Responsibility-Driven Approach|journal=ACM SIGPLAN Notices|date=1989|volume=24|issue=10|page=74|doi=10.1145/74878.74885}}</ref>。<!-- ここまで [[en:Object-oriented programming]] oldid=1057169575 の翻訳 --> |
|||
=== <!-- 以下、[[en:Object-oriented programming]] oldid=1047374345 の翻訳 -->SOLID、GRASPのガイドライン === |
|||
ただし、Smalltalkのクラス変数はC++やJavaのクラス変数とは異なる。Smalltalkにおいて、C++やJavaのクラス変数と同等となる変数は'''プール辞書''' ({{Lang|en|pool dictionary}}) と呼ばれる。 |
|||
[[SOLID]]のガイドラインは、プログラミングにおける五つの実践の頭文字をとった語呂合わせであり、マイケル・C・フェザーズ<ref>https://wiki.c2.com/?MichaelFeathers</ref>が考案し提唱したものである |
|||
=== メソッド === |
|||
* '''S''' : [[:en:Single responsibility principle|単一責任の原則(英語版)]] |
|||
'''[[メソッド (計算機科学)|メソッド]]''' ({{Lang|en|method}}) は特定の種類のメッセージの処理方法を記述したものである。メソッドも[[メソッド (計算機科学)#インスタンスメソッド|インスタンス・メソッド]]と[[メソッド (計算機科学)#静的メソッド|クラス・メソッド]]の2種にできる。インスタンス・メソッドはそのクラスの各インスタンスオブジェクトを操作し、クラス・メソッドはクラスオブジェクトを操作する。メソッドとの集まりはそのクラスのオブジェクトが処理可能なメッセージのカタログの機能を果たす。 |
|||
* '''O''' : [[開放/閉鎖原則]] |
|||
* '''L''' : [[リスコフの置換原則]] |
|||
* '''I''' : [[:en:Interface segregation principle|インターフェイス分離の原則(英語版)]] |
|||
* '''D''' : [[依存性逆転の原則]] |
|||
[[GRASP]](General Responsibility Assignment Software Patterns)は、[[:en:Craig Larman|クレーグ・ラーマン]]が提唱したもう一つガイドラインである。 |
|||
一例として、[[C++]]では、メソッドは'''メンバ関数''' ({{Lang|en|member function}}) や'''関数メンバ''' (function member) と呼ばれる。これはC++が[[グローバル関数]]との区別をつけることと、クラスを[[抽象データ型]]の拡張と位置づけ、非メッセージメタファな言語思想を持っているためである。これら言語ではメソッドをオブジェクト(=クラスやインスタンス)の持ち物として捉えず、クラスに定義された機能要素であると考える。メッセージメタファを否定するため、同時にメッセージを実行するメソッド(手法)ではありえない。 |
|||
<!-- 以上、[[en:Object-oriented programming]] oldid=1047374345 の翻訳 --> |
|||
== 形式意味論 == |
|||
==== クラスメソッド ==== |
|||
{{see also|プログラム意味論}} |
|||
[[メソッド (計算機科学)#静的メソッド|クラス・メソッド]]だが、オブジェクト指向の本義に立ち返れば、クラス・メソッドがあるということはクラスがメッセージをレシーブできるという事になる。 |
|||
クラスがメソッドを持つことは便利だが、クラスをオブジェクトとすると実行効率に劣るため、双方の利点を享受できるこのような折中的仕様を取る言語は多い。 |
|||
C++ではクラスはオブジェクトでは無いが、一方でクラスに属するメソッドは存在する。 |
|||
[[Eiffel]]ではクラスはオブジェクトでは無いためクラスのメソッドであるクラス・メソッドは存在しない。 |
|||
[[Smalltalk]]ではクラスもオブジェクトの一種であるため当然クラスはメソッドをもつ。 |
|||
'''各言語におけるクラスメソッドの呼称''' |
|||
クラス・メソッドは、C++では'''静的メンバ関数''' ({{Lang|en|static member function}}) と呼ばれる。これはクラスがオブジェクトでない言語にとってはクラス・メソッドより正確な表現であり適切である。("static" とはCの'''static変数'''に由来し'''auto変数'''の対語である。関数コールによりスタック上に生成される関数インスタンスに依存しない変数と、インスタンス生成有無にかかわらず実行できる関数の類似による。) |
|||
Javaではクラス・メソッドは'''静的メソッド''' ({{Lang|en|static method}}) とも呼ばれることもある。 |
|||
==== システムメソッド ==== |
|||
言語によっては特定の名前のインスタンス・メソッドやクラス・メソッドにオブジェクトの生成、初期化、複製、廃棄といった機能を固定的に割り当てている。 |
|||
==== コンストラクタとデストラクタ ==== |
|||
初期化に利用されるメソッドを'''[[コンストラクタ]]'''あるいは'''構築子''' ({{Lang|en|constructor}})、廃棄時に利用されるメソッドを'''[[デストラクタ]]'''と呼んで特別に扱うことが多い。 |
|||
コンストラクタが初期化だけを担う場合はイニシャライザあるいは初期化子 ({{Lang|en|initializer}}) と呼ばれることもある。 |
|||
Javaはオブジェクトの寿命管理に[[ガベージコレクション]]を用いるため、デストラクタをサポートしない。ただし、オブジェクトがガベージコレクションによって破棄されるときに呼び出される'''[[ファイナライザ]]''' ({{Lang|en|finalizer}}) をサポートし、{{Javadoc:SE|name=Object#finalize()|java/lang|Object|finalize()}}メソッドがその役割を果たす。ただし、ファイナライザはC++のデストラクタと違ってユーザーコードで明示的に呼び出すことはできない。ファイナライザが呼び出されるタイミングをプログラマが制御することはできず、最終防壁(フェイルセーフ)としての役割しか持たないため、Javaにおけるファイナライザは本当に必要でない限り使用するべきではない。C#もファイナライザをサポートする(構文はC++のデストラクタに似ており、かつてはデストラクタと呼ばれていたが、役割はJavaのファイナライザと同じである)。 |
|||
[[データ型]]の理論においては保持されるデータが必ずその型で認められる正しい値の範囲に収まることを保証するため、生成されるオブジェクトのデータ・メンバが必ず適切なコンストラクタによって初期化されるように求める。またオブジェクトが入出力機器や[[ファイル (コンピュータ)|ファイル]]や通信、[[プロセス]]や[[スレッド (コンピュータ)|スレッド]]、[[ウィンドウ]]と[[ウィジェット (GUI)|ウィジェット]]など[[ハードウェア]]や[[オペレーティングシステム]] (OS) が提供する資源を管理するために利用される場合に、コンストラクタやデストラクタでそれらの資源の使用開始(オープン処理)や使用終了(クローズ処理)をそれぞれ管理し、通常のメソッドでそれらにまつわる各種サービスを提供するようにすることで、それらのリソースがあたかもプログラム中のオブジェクトであるかのように自然に取り扱うことができるようになる([[RAII]])。 |
|||
C++やJavaなどでは、コンストラクタはクラスと同じ名前を持ち、戻り値を持たないメソッドとして定義される。C++では一部のコンストラクタは[[型変換演算子]]として、また[[暗黙の型変換]]にも利用される。 |
|||
=== ガベージコレクション === |
|||
オブジェクト指向プログラミング言語では、オブジェクトへの[[参照 (情報工学)|参照]]や[[ポインタ (プログラミング)|ポインタ]]が多用される。そのため、オブジェクトの[[メモリ]]への割り当てと破棄に関して、[[ガベージコレクション]]による自動管理機能を備えているものが多い。ただし、すべての言語が備えているわけではない。例えば、C++はガベージコレクションを備えていない。 |
|||
=== アクセスコントロール === |
|||
オブジェクト指向プログラミングにおいて、[[オブジェクト (プログラミング)|オブジェクト]]は、[[カプセル化]]されておりブラックボックスである。したがって、処理するメッセージのカタログ、つまりインタフェースだけが利用者に公開され、内部の詳細は隠されるのが基本である。しかし、あるクラスのインスタンスの内部だけで利用されるメソッドまで公開してしまうと、利用者にとって煩雑である。また、定数データ・メンバのようなものは一々メソッドでアクセスするようにせず公開してしまっても、カプセル化の利点は失われず効率的でもある。そこで、オブジェクトを定義するプログラマが各データ・メンバやメソッドについて公開・非公開を設定できる機能を用意している言語は多い。 |
|||
例えば、Javaでは、データ・メンバやメソッドの宣言にpublicと指定すれば、他オブジェクトから自由に利用でき('''公開'''と呼ばれる)、privateと指定すればオブジェクト内だけで利用できるようになる('''非公開'''と呼ばれる)。 |
|||
しかし、ある機能を提供するのに、一個ではなく一群のクラスに属するオブジェクトでそれを記述するのが相応しい事例がある。そのような場合、関係する一群のオブジェクト間でだけデータ・メンバやメソッドを利用できれば便利である。それを可能にするための拡張がいくつか存在する。例えば、継承を利用しているときに、あるクラスが子孫にだけ利用を許可したいデータ・メンバやメソッドがある場合、Javaではprotectedを指定することでそれを実現できる('''限定公開'''と呼ばれる)。また、ある一群の機能を実現するクラスの[[ライブラリ]]で、その実現に関連するクラスに属するオブジェクトだけがデータ・メンバやメソッド利用できるようにしたい場合も考えられる。また、Javaでは、ライブラリを構成するクラス群を表現する'''[[パッケージ (Java)|パッケージ]]''' ({{Lang|en|package}}) という仕組みがあり、特に指定がない場合は同一パッケージに属するクラスのオブジェクト間でのみデータ・メンバやメソッドを相互に利用可能である。その他にも、[[デザインパターン (ソフトウェア)|デザインパターン]]の一つである[[Facade パターン]]では、この仕組みがテクニックとして応用されている。また、C++ではフレンド宣言という仕組みがあり、あるクラスで外部非公開に指定されているデータ・メンバやメソッドについて、その利用を許可するクラスや関数のリストをクラス内に列挙することができる。 |
|||
なお、public、private、protectedというキーワードは、多くのプログラミング言語で用いられているが、その示す意味は言語ごとに差異があるため、注意が必要である。 |
|||
== 脚注 == |
== 脚注 == |
||
{{脚注ヘルプ}} |
{{脚注ヘルプ}} |
||
=== 注釈 === |
|||
{{Notelist2}} |
|||
=== 出典 === |
|||
{{Reflist}} |
{{Reflist}} |
||
== 出典 == |
|||
* {{Cite journal |
|||
|last=Kindler |
|||
|first=E. |
|||
|last2=Krivy |
|||
|first2=I. |
|||
|year=2011 |
|||
|title=Object-Oriented Simulation of systems with sophisticated control |
|||
|pages=313–343 |
|||
|publisher=International Journal of General Systems |
|||
|ref=harv |
|||
}} |
|||
* {{Cite book |
|||
|last=Lewis |
|||
|first=John |
|||
|last2=Loftus |
|||
|first2=William |
|||
|title=Java Software Solutions Foundations of Programming Design |
|||
|edition=6th |
|||
|year=2008 |
|||
|publisher=Pearson Education Inc. |
|||
|isbn=978-0-321-53205-3 |
|||
|ref=harv |
|||
}} |
|||
* {{cite web2 |
|||
|last=Kay |
|||
|first=Alan |
|||
|last2=Ram |
|||
|first2=Stefan |
|||
|title=Dr. Alan Kay on the Meaning of “Object-Oriented Programming” |
|||
|url=https://www.purl.org/stefan_ram/pub/doc_kay_oop_en |
|||
|website=www.purl.org |
|||
|access-date=2022-08-15 |
|||
|date=2003-07-23 |
|||
|ref={{sfnref|Meaning|2003}} |
|||
}} |
|||
* {{Cite journal |
|||
|last=McCarthy |
|||
|first=J. |
|||
|last2=Brayton |
|||
|first2=R. |
|||
|last3=Edwards |
|||
|first3=D. |
|||
|last4=Fox |
|||
|first4=P. |
|||
|last5=Hodes |
|||
|first5=L. |
|||
|last6=Luckham |
|||
|first6=D. |
|||
|last7=Maling |
|||
|first7=K. |
|||
|last8=Park |
|||
|first8=D. |
|||
|last9=Russell |
|||
|first9=S. |
|||
|date=March 1960 |
|||
|title=LISP I Programmers Manual |
|||
|url=http://history.siam.org/sup/Fox_1960_LISP.pdf |
|||
|page=88f |
|||
|publisher=Artificial Intelligence Group, [[:en:M.I.T. Computation Center]] and Research Laboratory |
|||
|author2-link=:en:Robert Brayton (computer scientist) |
|||
|author3-link=:en:Daniel Edwards (programmer) |
|||
|author4-link=:en:Phyllis Fox |
|||
|author5-link=:en:Louis Hodes |
|||
|author6-link=:en:David Luckham |
|||
|author7-link=:en:Klim Maling (programmer) |
|||
|author8-link=:en:David Park (computer scientist) |
|||
|author9-link=:en:Steve Russell (computer scientist) |
|||
|place=[[ボストン]], [[マサチューセッツ]] |
|||
|quote=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". |
|||
|url-status=dead |
|||
|archive-date=17 July 2010 |
|||
|archiveurl=https://web.archive.org/web/20100717111134/http://history.siam.org/sup/Fox_1960_LISP.pdf |
|||
|ref={{sfnref|LISP 1 Programmers Manual|1960}} |
|||
}} |
|||
* {{Cite book |
|||
|last=McCarthy |first=John |
|||
|author-link=:en:John McCarthy (computer scientist) |
|||
|title=LISP 1.5 Programmer's Manual |
|||
|url=https://archive.org/details/lisp15programmer00john/page/105 |
|||
|year=1962 |
|||
|publisher=[[:en:MIT Press]] |
|||
|isbn=978-0-262-13011-0 |
|||
|page=[https://archive.org/details/lisp15programmer00john/page/105 105] |
|||
|quote=Object — a synonym for atomic symbol |
|||
|last2=Abrahams |
|||
|first2=Paul W. |
|||
|last3=Edwards |
|||
|first3=Daniel J. |
|||
|author3-link=:en:Daniel Edwards (programmer) |
|||
|last4=Hart |
|||
|first4=swapnil d. |
|||
|last5=Levin |
|||
|first5=Michael I. |
|||
|df=dmy-all |
|||
|ref={{sfnref|LISP 1.5 Programmers Manual|1962}} |
|||
}} |
|||
* {{Cite web |
|||
|url=http://handle.dtic.mil/100.2/AD404549 |
|||
|title=Sketchpad: A Man-Machine Graphical Communication System |
|||
|last=Sutherland |
|||
|first=I. E. |
|||
|date=1963-01-30 |
|||
|publisher=Technical Report No. 296, Lincoln Laboratory, Massachusetts Institute of Technology via Defense Technical Information Center (stinet.dtic.mil) |
|||
|access-date=17 July 2019 |
|||
|ref={{sfnref|Sutherland|1963}} |
|||
}} |
|||
* {{cite book |
|||
|last1=Ali |
|||
|first1=Junade |
|||
|title=Mastering PHP Design Patterns |
|||
|date=2016-09-28 |
|||
|publisher=Packt Publishing Limited |
|||
|location=Birmingham, England, UK |
|||
|isbn=978-1-78588-713-0 |
|||
|edition=1 |
|||
|language=en |
|||
|ref=harv |
|||
}} |
|||
* {{cite journal |
|||
|last1=Nygaard |
|||
|first1=Kristen |
|||
|last2=Dahl |
|||
|first2=Ole-Johan |
|||
|title=Development of the SIMULA languages |
|||
|journal=ACM SIGPLAN Notices |
|||
|pages=245–272 |
|||
|volume=13 |
|||
|issue=8 |
|||
|publisher=Association for Computing Machinery |
|||
|date=1978-08-01 |
|||
|doi=10.1145/960118.808391 |
|||
|ref=harv |
|||
}} |
|||
* {{Cite journal |
|||
|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 |
|||
|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 = 22 October 2021 |
|||
|ref=harv |
|||
}} |
|||
* {{Cite journal |
|||
|first=Alan |
|||
|last=Kay |
|||
|title=The Early History of Smalltalk |
|||
|journal=ACM SIGPLAN Notices |
|||
|volume=28 |
|||
|issue=3 |
|||
|date=1993-03-01 |
|||
|pages=69–95 |
|||
|doi=10.1145/155360.155364 |
|||
|publisher=Association for Computing Machinery |
|||
|ref=harv |
|||
}} |
|||
* {{Cite journal |
|||
|last = Holmevik |
|||
|first = Jan Rune |
|||
|title = Compiling Simula: A historical study of technological genesis |
|||
|journal = IEEE Annals of the History of Computing |
|||
|volume = 16 |
|||
|issue = 4 |
|||
|pages = 25–37 |
|||
|year = 1994 |
|||
|doi = 10.1109/85.329756 |
|||
|s2cid = 18148999 |
|||
|ref=harv |
|||
}} |
|||
* {{Cite book |
|||
|title=Touch of Class: Learning to Program Well with Objects and Contracts |
|||
|first=Bertrand |
|||
|last=Meyer |
|||
|publisher=Springer Science & Business Media |
|||
|year=2009 |
|||
|isbn=978-3-540-92144-8 |
|||
|pages=329 |
|||
|bibcode=2009tclp.book.....M |
|||
|ref=harv |
|||
}} |
|||
== 関連項目 == |
== 関連項目 == |
||
<!-- ここから [[en:Object-oriented programming]] oldid=1055370410 の翻訳 --> |
|||
{{Wikibooks|オブジェクト指向|オブジェクト指向}} |
|||
<!-- * [[Comparison of programming languages (object-oriented programming)]] --> |
|||
* [[メッセージ (コンピュータ)]] |
|||
<!-- * [[Comparison of programming paradigms]] --> |
|||
* [[メソッド (計算機科学)]] |
|||
<!-- * [[Component-based software engineering]] --> |
|||
* [[フィールド (計算機科学)]] |
|||
* [[契約プログラミング]] |
|||
* [[インスタンス変数]] |
|||
<!-- * [[Object association]] --> |
|||
* [[クラス変数]] |
|||
* [[クラス (コンピュータ)]] |
|||
* [[インスタンス]] |
|||
* [[カプセル化]] |
|||
* [[継承 (プログラミング)|継承]] |
|||
* [[委譲]] |
|||
* [[プログラミング言語]] |
|||
* [[オブジェクト指向モデリング]] |
|||
* [[オブジェクト指向分析設計]] |
|||
* [[オブジェクト指向]] |
|||
* [[オブジェクトデータベース]] |
* [[オブジェクトデータベース]] |
||
<!-- * [[Object model reference]] --> |
|||
* [[トップダウン設計とボトムアップ設計]] |
|||
<!-- * [[Object modeling language]] --> |
|||
* [[オブジェクト指向分析設計]] |
|||
<!-- * [[Object-relational impedance mismatch]] (and [[The Third Manifesto]]) --> |
|||
* [[オブジェクト関係マッピング]] |
* [[オブジェクト関係マッピング]] |
||
=== システム === |
|||
* [[:en:CADES|CADES]] |
|||
* [[Common Object Request Broker Architecture]] (CORBA) |
|||
* [[Distributed Component Object Model]] |
|||
* [[:en:Distributed Data Management Architecture|Distributed Data Management Architecture]] |
|||
* [[:en:Jeroo|Jeroo]] |
|||
=== モデリング言語 === |
|||
* [[:en:IDEF4|IDEF4]] |
|||
* [[インタフェース記述言語]] |
|||
* [[:en:Lepus3|Lepus3]] |
|||
* [[統一モデリング言語|UML]] |
|||
<!-- ここまで [[en:Object-oriented programming]] oldid=1055370410 の翻訳 --> |
|||
{{Normdaten}} |
{{Normdaten}} |
||
{{プログラミング言語の関連項目}} |
{{プログラミング言語の関連項目}} |
||
{{デフォルトソート:おふしえくとしこうふろくらみんく}} |
{{デフォルトソート:おふしえくとしこうふろくらみんく}} |
||
[[Category:オブジェクト指向|*ふろくらみんく]] |
[[Category:オブジェクト指向|*ふろくらみんく]] |
2024年8月3日 (土) 12:42時点における最新版
この項目「オブジェクト指向プログラミング」は途中まで翻訳されたものです。(原文:en:Object-oriented programming(13:57, 15 November 2021 UTC)の翻訳) 翻訳作業に協力して下さる方を求めています。ノートページや履歴、翻訳のガイドラインも参照してください。要約欄への翻訳情報の記入をお忘れなく。(2021年11月) |
プログラミング・パラダイム |
---|
オブジェクト指向プログラミング(オブジェクトしこうプログラミング、英: object-oriented programming, OOP)とは、「オブジェクト」という概念に基づいたプログラミングパラダイムの一つである。
OOPでは、相互に作用するオブジェクトを組み合わせてプログラムを設計する[1][2]。
OOPの方法として、クラスベースOOPとプロトタイプベースOOPがある。 クラスベースOOPでは、オブジェクトが属する集合としてクラスを定義し、クラス定義からそのインスタンスとしてオブジェクトを生成する。 プロトタイプベースOOPでは既存のオブジェクト(プロトタイプ)を複製し、プロトタイプの複製に変更を加えることで様々な対象を表すオブジェクトを生成する。
広く使われているプログラミング言語の多く、例えばC++やJavaやPythonなどは、マルチパラダイムであるが、程度の差はあれ、オブジェクト指向プログラミングをサポートしており、大抵は命令型や手続き型プログラミングとの組み合わせで用いられる。
歴史
[編集]アラン・ケイによれば “object-oriented”(オブジェクト指向)という言葉は、1967年ごろケイ自身が考案したものであるという[3]。しかし、現在のオブジェクト指向プログラミングという文脈における「オブジェクト」や「指向」を表す用語が初めて登場したのは、1950年代後半から1960年代前半にかけてのマサチューセッツ工科大学(MIT)においてである。 1960年代初頭の人工知能グループ界隈では、「オブジェクト」はプロパティ(属性)を持つ個体識別可能なアイテム(LISPの atom)を意味していた[4][5]。 後にケイは、1966年にLISPの内部構造を詳細に理解したことが彼の考え方に強い影響を与えたと述べている[3]。
MITにおける初期の例としては、この他にも、1960年から1961年にかけてアイバン・サザランドが作成したSketchpadが挙げられる。サザランドは、1963年の技術レポートの用語集 (Sketchpadに関する自身の博士論文をもとにしたもの)で、グラフィカルなインタラクションに特化しているとはいえ「オブジェクト」と「インスタンス」の概念を定義している (クラスの概念は"master"または"definition"として把握されている)。[6] また、MIT版のALGOLであるAED-0では、データ構造 (この言語の方言では"plexes"と呼称)と手続きを直接結びつけ、後に「メッセージ」、「メソッド」、「メンバ関数」と呼ばれるようなものの萌芽がみられる。[7]
1962年、クリステン・ニゴールはノルウェー計算センターでシミュレーション言語のプロジェクトを開始した。これは彼が以前に用いたモンテカルロ法と実世界のシステムを概念化する仕事に基づくものであった。オーレ=ヨハン・ダールが正式にプロジェクトに参加し、UNIVAC I (UNIVAC 1107) 上で動作するSimulaプログラミング言語が設計された。Simulaは、クラスやオブジェクト、継承、ダイナミックバインディングなど、今日のオブジェクト指向プログラミングには不可欠である重要な概念を導入した。[8] Simulaはまた、プログラミングにおけるデータ保全を考慮して設計されたものでもあった。プログラミングのデータ保全のために参照カウントによる検出プロセスが実装されたのに加え、最終手段としてガベージコレクタが主記憶装置(メモリ)内の使用されていないオブジェクトを削除するようになっていた。しかし、データオブジェクトの概念は1965年には既に確立されていたものの、プライベートやパブリックといった変数のスコープのレベルによるデータのカプセル化については、アクセスする手続きもまた隠蔽できなければならなかったため、Simulaでは実装されなかった。[9]
初期の段階では、Simulaはプログラミング言語ALGOL 60のための手続きパッケージとされていた。しかし、ALGOLによる制約に不満を感じた研究者たちは、UNIVAC ALGOL 60コンパイラを使用した本格的なプログラミング言語としてSimulaを開発することにした。ダールとニゴールは1965年から1966年にかけてSimulaの普及に尽力し、スウェーデン、ドイツ、ソビエト連邦などでSimulaの使用が増加した。1968年には、バロース B5000上で広く利用されるようになり、後にはURAL-16コンピュータ上にも実装された。1966年、ダールとニゴールはSimulaのコンパイラを書いた。彼らは、SIMSCRIPT (自由形式の英語的な汎用シミュレーション言語)を実装に用いて、アントニー・ホーアのレコード・クラス概念を取り入れることに熱心に取り組んだが、彼らは、一般化されたプロセスの概念として、レコード・クラスの属性を保持する層と、接頭辞 (prefix) の系列を保持する層の二層構造とする方式に辿り着いた。 接頭辞の系列を通じて、プロセスは先行する定義を参照し、それらの属性を追加することができる。このようにしてSimulaは、クラスとサブクラスの階層を導入し、これらのクラスからオブジェクトを生成することを可能にする方法を導入することとなった。[7]
1972年にはIBM System/360およびIBM System/370のIBMメインフレーム用にSimula 67コンパイラが完成[8]。同年、フランスのCII 10070およびCII Iris 80メインフレーム用のSimula 67コンパイラが無償で提供された。1974年には、Simulaユーザー会は23カ国のメンバーを有するまでになっていた。1975年初頭、DECsystem-10メインフレームファミリー用のSimula 67コンパイラが無償でリリースされ、同年8月までにDECsystem-10のSimula 67コンパイラは28サイトにインストールされた (そのうちの22サイトは北米)。オブジェクト指向のプログラミング言語としてSimulaは、貨物港における船舶と積載貨物の動きを調査・改善するための研究のような、物理モデリングの研究に携わる研究者に主に利用されていた[8]。
1970年代、Xerox パロアルト研究所(PARC)において、アラン・ケイ、ダン・インガルス、アデル・ゴールドバーグらによって、プログラミング言語Smalltalkの最初のバージョンが開発された。Smaltalk-72はプログラミング環境を含み、動的型付けであり、当初はコンパイルしてからの実行ではなくインタプリタ実行であった。Smalltalkは、言語レベルでのオブジェクト指向の適用と、グラフィカルな開発環境で注目されたが、Smalltalkが様々なバージョンを経て成長するにつれ、この言語への関心も高まっていった[10]。 SmalltalkはSimula 67で導入されたアイデアの影響を受けてはいるものの、クラスを動的に生成・変更できるなど、完全に動的なシステムとして設計された[11]。
1970年代、SmalltalkはLispコミュニティに影響を与え、Lispコミュニティは、Lispマシンを通じて開発者に紹介されたオブジェクトベースの技術を取り入れた。Lispの様々な拡張機能(LOOPS やFlavorsなどが導入した多重継承やMixin)の試みは、最終的に関数型プログラミングとオブジェクト指向プログラミングを統合し、メタオブジェクト・プロトコルによる拡張を可能にしたCommon Lispのオブジェクト指向システム (CLOS) へとつながった。 1980年代には、メモリ上のオブジェクトをハードウェアでサポートするプロセッサ・アーキテクチャを設計する試みがいくつか行われたが、Intel iAPX 432やLinn Smart、Rekursivなど、いずれも商業的に成功しなかった。
1981年、ゴールドバーグはByte Magazine 8月号のSmalltalk特集号で、Smalltalkとオブジェクト指向プログラミングをより多くの人々に紹介した。 1986年、ACMが主催する第一回OOPSLAが開催され、予想に反して1,000人が参加した。1980年代半ばには、ITTでSmalltalkを使っていたブラッド・コックスによってObjective-Cが開発され、博士論文でSimulaを扱っていたビャーネ・ストロヴストルップよってオブジェクト指向のC++が作られた[10]。 1985年には、バートランド・メイヤーもEiffelの最初の設計を行った。ソフトウェアの品質に焦点を当てたEiffelは、純粋なオブジェクト指向プログラミング言語であり、ソフトウェアのライフサイクル全体をサポートする記法をもつ。メイヤーは、ソフトウェア工学とコンピュータサイエンスの少数の重要なアイデアに基づいたEiffelでのソフトウェア開発手法をオブジェクト指向入門で解説している。Eiffelでは、メイヤーが開発した信頼性担保の機構である契約プログラミングが、開発手法と言語の双方に不可欠な要素となっている。
1990年代前半から半ばにかけて、オブジェクト指向プログラミングは、その技術をサポートするプログラミング言語が広く普及したことにより、プログラミングパラダイムとして主要なものとなった。その中には、Visual FoxPro 3.0[注 1][12][13]、C++[14]、Delphi[15]などがある。 その勢力は、オブジェクト指向プログラミング技術に支えられたグラフィカルユーザインタフェースの人気向上と共に高まった。動的なGUIライブラリとOOP言語が密接に連携している例としては、Smalltalkを規範にしたCのオブジェクト指向の動的メッセージング拡張であるObjective-Cで書かれたmacOSのCocoaフレームワークなどが挙げられる。また、OOPツールキットの存在は、イベント駆動型プログラミングの人気を高めることにも繋がった(ただし、この概念はOOPに限定されるものではない)。 チューリッヒ工科大学では、ニクラウス・ヴィルトらが、データ抽象化やモジュール化プログラミングなどの研究を行っていた (ただし、これらは1960年代以前にも一般的に使われてはいた)。 1978年に発表されたModula-2にはこの2つが盛り込まれており、その後に発表されたOberonでは、オブジェクト指向やクラスなどに対する独自のアプローチが盛り込まれている[16]。
オブジェクト指向の機能は、Ada、BASIC、Fortran、Pascal、COBOLなど、既存の多くの言語に追加されていったが、しかし、設計当初にこれらの機能を想定していなかった言語に追加した場合、コードの互換性や保守性には問題が生じることが多かった。
最近では、主としてオブジェクト指向でありながら、手続き型プログラミングの方法論にも対応した言語が数多く登場している。そのような言語としては、PythonやRubyがある。最近の商業的なオブジェクト指向言語で最も重要なものには、サン・マイクロシステムズ社が開発したJavaや、Microsoftの.NETプラットフォーム用に設計されたC#、Visual Basic .NET (VB.NET) が挙げられる。 これら二つのフレームワークは、実装を抽象化することによるOOP使用の利点をそれぞれの方法で示している。VB.NETとC#間では言語間継承をサポートしており、一方の言語で定義されたクラスが他方の言語で定義されたクラスをサブクラス化することができる[17]。
OOPLの特徴
[編集]オブジェクト指向プログラミング言語 (OOPL) では、オブジェクトを使用するが、言語仕様でOOP対応を謳っていても、関連する技術や構造のすべてが言語機能により直接サポートされているわけではない。以下に挙げる特徴は、特に言及されている例外を除いて、クラス指向やオブジェクト指向の傾向が強いとされる言語 (あるいはOOPをサポートするマルチパラダイムプログラミング言語)に共通すると考えられるものである。
非OOPLとの共通点
[編集]- 変数
- 整数型や英数字の文字のような形式化された少数の組み込みデータ型の情報、または、文字列、リスト、ハッシュテーブルなどのデータ構造に、組み込み型もしくは、ポインタが格納されたものを結果として格納することができる。
- 手続き(関数、メソッド、サブルーチンとも呼ばれる)
- 入力を受け取り、出力を生成し、データを操作する。近年の言語には、ループや条件構文のような構造化プログラミングの構成要素が含まれる。
モジュラープログラミングサポートでは、手続きをファイルやモジュールにまとめて整理する機能がある。モジュールは名前空間を持つため、あるモジュールの識別子が、他のモジュールの同名の手続きや変数と衝突することを避けることができる。
クラスとオブジェクト
[編集]オブジェクト指向プログラミング(OOP)をサポートする言語は、コードの再利用と拡張性のために、典型的には、クラスまたはプロトタイプの形で継承を使用する。クラスを使用するものは、主に二つの概念をサポートする。
- クラス
- 与えられた型やクラスのオブジェクトのデータ形式やそれらを利用可能な手続きの定義であり、また、データや手続き (クラスメソッドとも呼ばれる)そのものを含む場合もある。つまり、クラスは、メンバーとなるデータや手続きを含むものである。
- オブジェクト
- クラスのインスタンス
オブジェクトは、システムが扱おうとする(多くは現実世界の)対象を表現したものである。例えば、描画アプリケーションにおける「円」・「四角」・「メニュー」などのオブジェクトや、オンラインショッピングシステムにおける「ショッピングカート」・「顧客」・「商品」などのオブジェクトがある[18]。 オブジェクトは、ファイルのオープンを表すオブジェクトや、米国慣用単位からメートル法に変換するサービスを提供するオブジェクトのように、より抽象的なエンティティを表すこともある。
各々のオブジェクトは、特定のクラスのインスタンスと呼ばれる (例えば、name
フィールドに "Mary"
が設定されているオブジェクトは、クラスEmployee
のインスタンスとなる)。OOPの手続きはメソッドと呼ばれ、変数は、フィールド、メンバー、属性、プロパティとも呼ばれる。関連して、以下のような用語がある
- クラス変数
- クラス自体に属する。変数をクラス全体に唯一のものとして所有する。
- インスタンス変数または属性
- 各々のオブジェクトに属する。データはオブジェクトごとに所有する。
- メンバ変数
- 特定のクラスで定義されるクラス変数とインスタンス変数の両方を指す。
- クラスメソッド
- クラス自体に属する。クラス変数へのアクセスのみ有し、手続き呼び出しからの入力のみ受け付ける。
- インスタンスメソッド
- 各々のオブジェクトに対して、呼び出された特定のオブジェクトのインスタンス変数、入力、およびクラス変数にアクセスできる。
オブジェクトは、複雑な内部構造を持った変数のようにアクセスされるが、多くの言語で実質的にはポインタでありインスタンス (ヒープやスタック内のメモリ上オブジェクト)への参照として機能する。オブジェクトは、内部コードと外部コードを分離を可能とする抽象化の層を提供する。外部のコードは、特定の入力引数の組み合わせで特定のインスタンスメソッドを呼び出したり、インスタンス変数を読み込んだり、インスタンス変数に書き込んだりすることで、オブジェクトを使用することができる。オブジェクトは、コンストラクタと呼ばれるクラス内の特定メソッドを呼び出すことで生成される。プログラムは実行中に、それぞれ独立して操作することが可能な同じクラスのインスタンスを多数作成することができる。これは、同じ手続きを異なるデータセットで簡便に利用する方法となる。
クラスを使用するOOPをクラスベース・プログラミングと呼ぶことがあるが、プロトタイプベース・プログラミングではクラスを使用しないのが一般的である。そのため、オブジェクトとインスタンスという概念の定義は、それぞれで大きく異なるが類似した用語が用いられている。
言語によっては、トレイトやmixinのような概念を用いてクラスやオブジェクトを構成することが可能である。
クラスベース対プロトタイプベース
[編集]クラスベースの言語では、予めクラスが定義され、そのクラスに基づいてオブジェクトがインスタンス化される。例えば、appleとorangeという2つのオブジェクトが、Fruitというクラスからインスタンス化された場合、それらは本質的には果物であり、同じように取り扱えることの保証がされる。
プロトタイプベースの言語では、オブジェクトが主要な実体である。クラスは存在しない。オブジェクトのプロトタイプとは、あるオブジェクトからリンクされている別のオブジェクトに過ぎない。すべてのオブジェクトは一つのプロトタイプリンクを持つ (一つのみ)。新しいオブジェクトは、プロトタイプとして選ばれた既存のオブジェクトに基づいて作成することができる。fruitオブジェクトが存在し、appleとorangeの両方がfruitをプロトタイプとしている場合、2つの異なるオブジェクトappleとorangeを果物と考えることができる。fruit「クラス」という概念は明示的には存在しないが、同じプロトタイプを共有するオブジェクトの同値クラスとしては存在する。プロトタイプの属性やメソッドは、このプロトタイプで定義された同値クラスのすべてのオブジェクトから委譲先とされる。オブジェクト固有の属性やメソッドは、同値クラスの他のオブジェクトに共有されない場合がある。例えば、属性sugar_contentはappleには予期せず存在しない場合がある。プロトタイプで実装できるのは単一継承のみである。
動的ディスパッチとメッセージパッシング
[編集]メソッドの呼び出しに応じて実行する手続きのコードを選択するのは、外在するコードではなく、オブジェクトの責任である。典型的には、オブジェクトに関連付けられたテーブルから実行時にメソッドを検索するが、この機能は動的ディスパッチとして知られており、抽象データ型 (またはモジュール)において、すべてのインスタンスの操作が静的に実装されているのとは対照的である。呼び出しの変化が、呼び出されたオブジェクトの単一の型にのみには依らない場合 (つまり複数のオブジェクトがメソッド選択に関与する場合)、多重ディスパッチと呼ばれる。
メソッド呼び出しは、メッセージパッシングとも呼ばれる。これは、メソッド呼び出しを、ディスパッチのためにオブジェクトに渡されるメッセージ (メソッドの名前とその入力引数)として概念化したものである。
カプセル化
[編集]カプセル化とは、オブジェクト指向プログラミングにおいて、データとそのデータを操作する関数を結び付け、両者を外部からの干渉や誤用から守ることである。データのカプセル化は、OOPの重要な概念である情報隠蔽にも通じる。
クラスがメソッドを通じてのみオブジェクトの内部データへのアクセスを許可し、それ以外の呼び出しコードにアクセスを許可しない場合、これはカプセル化として知られる強力な抽象化、または情報隠蔽の形態である。いくつかの言語 (Javaなど)では、クラスがアクセス制限を明示的に行うことができる。例えば、内部データであることをprivate
というキーワードで指定し、クラス外のコードが使用することを意図したメソッドをpublic
というキーワードで指定することができる。また、メソッドはpublic、private、またはprotected
(同クラスとそのサブクラスからのアクセスは許可するが、異なるクラスのオブジェクトからのアクセスは許可しない)のように中間のアクセスレベルとすることもできる。また他の言語 (Pythonなど)では、アクセス制限は、命名法などの慣例によってのみ強制される (例えば、private
のメソッドはアンダースコアで始まる名前を持つ、など)。カプセル化することで、外部のコードがオブジェクトの内部動作に関与してしまうことを防ぐことができ、リファクタリングを容易にする。例えば、クラスの設計者は、外部のコードは変更することなく、そのクラスのオブジェクト内部のデータ表現を変更することができる (公開されているメソッドの呼び出しが同じように動作する限りにおいて)。また、特定のデータに関連するすべてのコードを同じクラスに配置することで、他のプログラマが理解しやすいように整理することもできる。カプセル化は、疎結合を促進する技術である。
コンポジション、継承、委譲
[編集]オブジェクトは、そのインスタンス変数に他のオブジェクトを含めることができ、これをオブジェクトコンポジションと呼ぶ。例えば、"従業員"クラスのオブジェクトは、"名前" や "役職"といった自身のインスタンス変数に加えて、"住所"クラスのオブジェクトを (直接またはポインタを介して)含むことができる。 オブジェクトコンポジションは、"has-a" の関係を表現するために使用できる。例えば、すべての従業員は住所を持っているので、すべての"従業員"オブジェクトは、"住所"オブジェクトを格納する場所 (オブジェクトに直接埋め込まれていることも、ポインターで指定された別の場所に格納されることもある)にアクセスできる。
クラスをサポートする言語は、大抵は継承をサポートしている。継承とは、クラスを「○○は△△である」という関係("is-a-type-of")の階層に配置することであるが、例えば、Employee
クラスは Person
クラスを継承する場合、親クラスで利用できるデータやメソッドは、子クラスでも同じ名前で利用可能である。また、Person
クラスは、first_name
と last_name
という変数を make_full_name()
というメソッドで定義した場合、これらの定義はEmployee
クラスでも利用可能である。加えて、Employee
クラスには変数 position
と salary
を追加することもできる。この手法では、同じ手続きやデータ定義を簡単に再利用できるだけでなく、現実世界の関係を直感的に反映できる可能性を広げる。開発者は、データベースのテーブルやプログラミングのサブルーチンを扱うのではなく、開発アプリケーションのユーザーがより精通しているドメインのオブジェクトを扱うことができる[19]。
サブクラスはスーパークラスで定義されたメソッドをオーバーライドできる。言語よっては多重継承が可能だが、多重継承ではオーバーライドの解決は複雑になる可能性がある。また、言語によってはmixinを特別にサポートしているものもあるが、多重継承をサポートする言語では、mixinは単に is-a-type-of の関係を表すことのないクラスの一つである。mixinは典型的には、同一のメソッドを複数のクラスに追加するために使われる。例えば、共通の親クラスを持たないFileReader
クラスとWebPageScraper
クラスに、unicode_to_ascii()
というメソッドを持つUnicodeConversionMixin
クラスを含ませる(mixinする)ことにより共通のメソッドを提供することができる。
抽象クラスは、オブジェクトへインスタンス化することはできない。インスタンス化できる他の具象クラスが継承するためにのみ存在する。Javaでは、final
キーワードを用いて、クラスがサブクラス化されるのを防止できる。
Composition over inheritanceの方針は、継承の代わりに合成を使って has-a 関係を実装することを提唱している。例えば、EmployeeクラスはPersonクラスを継承する代わりに、各Employeeオブジェクトの内部にPersonオブジェクトを含めることで、仮にPersonクラスが公開された属性やメソッドを多数持っていても、外部のコードからは隠せるようにする。また、Goのように、継承を全くサポートしていない言語も存在する。
開放/閉鎖原則は、クラスやメソッドは「拡張に対しては開放的であるが、変更に対しては閉鎖的であるべき」という原則を提唱している。
委譲もまた、継承の代わりに利用できる言語機能である。
ポリモーフィズム
[編集]サブタイピング (ポリモーフィズムの一形態)では、呼び出すコードが、サポートされている階層のどのクラスを操作しているのか (親クラスなのかその子孫なのか)という詳細には関知しないことが可能である。一方、継承階層内のオブジェクト間では、同じ操作名でも挙動が異なる場合がある。
例えば、Circle型とSquare型のオブジェクトが、Shapeという共通のクラスから派生している場合、Shapeの各型のDraw関数は、それぞれの描画に必要な機能を実装しているが、呼び出しのコードは、描画されるShapeが特定の型であるかどうかには無関心でいられる。
これもまた、クラス階層からコードを引き離して単純化し、強力な関心の分離を可能にする抽象化の一種である。
オープンな再帰
[編集]オープンな再帰[20]をサポートする言語では、オブジェクトのメソッドは同じオブジェクト上の他のメソッドや自分自身を呼び出すことができる。通常はthis
やself
と呼ばれる特別な変数やキーワードを使用して呼び出しをするのが一般的であるが、この変数は「遅延結合」であり、あるクラスで定義されたメソッドが、そのサブクラスで後から定義された別のメソッドを呼び出すことができる。
デザインパターン
[編集]継承とBehavioral subtyping
[編集]継承は意味論的には is-a の関係を作るため、サブクラスからインスタンス化されたオブジェクトは、スーパークラスからインスタンス化されたオブジェクトの代わりに、常に安全に使用できる、と推測するのは直感的ではあるが、この直観は、ほとんどのOOPL、特にミュータブルなオブジェクトを許可している言語では誤りである。 (ミュータブルなオブジェクトを持つ)OOPLの型検査器によって強制される部分型付け (部分型多相/サブタイピング多相)では、いかなる状況でも、振る舞いにおける部分型付け (Behavioral subtyping) は保証することはできない。 Behavioral subtyping は一般に決定不能であり、プログラム (コンパイラ)では実装できない。クラスやオブジェクトの階層は、文法間違いでは検出できない使い方がされる可能性を考慮に入れて、慎重に設計する必要がある。この問題はリスコフの置換原則としても知られている。
GoFデザインパターン
[編集]オブジェクト指向とデータベース
[編集]OOPL と関係データベース管理システム (RDBMS) は、どちらも今日[update]のソフトウェアとして非常に一般的であるが、双方を接続する場合、関係データベースは、オブジェクトを直接格納しないため (ただし、今日ではこれに近しい拡張機能を持つ RDBMS も存在する)、この二つの世界を橋渡しすることが一般的な需要として擡頭した。アクセス方法やデータパターンを OOPL と RDB との間で橋渡しする際の問題は、オブジェクト-リレーションのインピーダンスミスマッチと呼ばれている。 この問題に対処するためのアプローチはいくつかある。欠点のない一般的な解決策といえるものはない[21]が、代表的なものとして、オブジェクト関係マッピング(ORM)があり、Visual FoxProなどのIDE言語や、Java Data Objects、Ruby on RailsのActive Recordなどのライブラリが存在する。
また、RDBMS を代替するオブジェクトデータベースも存在するが、技術的にも商業的にも RDBMS ほど広く成功は収めていない。
OOPと制御構造
[編集]OOPは、ソースコードのコードの再利用性やソフトウェアの保守性を高めるよう発展してきたが[22] 、ある時期までは制御フローの透過的な表現については、あまり省みられることもなく、コンパイラが任意に処理すれば良いと考えられてきた。しかし、OOPでの実現にはある種の困難を伴うものの、並列ハードウェアやマルチスレッドコーディングの重要性が増すにつれ透過的な制御フローの開発は重要になってきている[23][24][25][26]。
責任駆動設計 対 データ駆動設計
[編集]責任駆動設計では、クラスは、共有する情報とそれを扱う責務という観点から定義されるべきであるとし、クラス定義 (とその利用者)の契約として設計する。Wirfs-BrockとWilkersonは、責任駆動設計と対比して、データ駆動設計は、クラスが保持すべきデータ構造のみを中心に定義されるとし、責任駆動型の設計が望ましいとしている[27]。
SOLID、GRASPのガイドライン
[編集]SOLIDのガイドラインは、プログラミングにおける五つの実践の頭文字をとった語呂合わせであり、マイケル・C・フェザーズ[28]が考案し提唱したものである
- S : 単一責任の原則(英語版)
- O : 開放/閉鎖原則
- L : リスコフの置換原則
- I : インターフェイス分離の原則(英語版)
- D : 依存性逆転の原則
GRASP(General Responsibility Assignment Software Patterns)は、クレーグ・ラーマンが提唱したもう一つガイドラインである。
形式意味論
[編集]脚注
[編集]注釈
[編集]- ^ 1995年6月 Visual FoxPro 3.0, FoxPro は手続き型言語からオブジェクト指向言語へと進化した。Visual FoxPro 3.0では、データベースコンテナ、シームレスなクライアント/サーバー機能、ActiveXのサポート、OLEオートメーションとヌルのサポートが導入された。Summary of Fox releases
出典
[編集]- ^ Kindler & Krivy 2011.
- ^ Lewis & Loftus 2008, §1.6 "Object-Oriented Programming".
- ^ a b Meaning 2003.
- ^ LISP 1 Programmers Manual 1960, p. 88f.
- ^ LISP 1.5 Programmers Manual 1962, p. 105.
- ^ Sutherland 1963.
- ^ a b Nygaard & Dahl 1978.
- ^ a b c Holmevik 1994.
- ^ Dahl 2004.
- ^ a b Meyer 2009.
- ^ Kay 1993.
- ^ FoxProの歴史: Foxprohistory.org
- ^ 1995年のVisual FoxPro 3.0 レビュー/ガイド: DFpug.de
- ^ Khurana, Rohit (1 November 2009). Object Oriented Programming with C++, 1E. ISBN 978-81-259-2532-3
- ^ マイナビTECH+: Delphiがトップ20位から脱落: 「Delphiは2001年6月にトップ20位入りを果たし、2000年代初頭には最も人気のある統合開発環境として広く使用されていた。」[1]
- ^ Wirth, Niklaus. From Modula to Oberon and the programming language Oberon (Report). ETH Technical Reports D-INFK. Vol. Band 82. Wiley.
- ^ 共通型システム|Microsoft Docs [2]
- ^ Booch, Grady (1986). Software Engineering with Ada. Addison Wesley. p. 220. ISBN 978-0-8053-0608-8 . "Perhaps the greatest strength of an object-oriented approach to development is that it offers a mechanism that captures a model of the real world."
- ^ Jacobsen, Ivar; Magnus Christerson; Patrik Jonsson; Gunnar Overgaard (1992). Object Oriented Software Engineering. Addison-Wesley ACM Press. pp. 43–69. ISBN 978-0-201-54435-0
- ^ 『型システム入門』オーム社、2013年、185頁。 18.10 selfを介したオープンな再帰
- ^ Neward, Ted (26 June 2006). “The Vietnam of Computer Science”. Interoperability Happens. 4 July 2006時点のオリジナルよりアーカイブ。2 June 2010閲覧。
- ^ Ambler, Scott (1 January 1998). “A Realistic Look at Object-Oriented Reuse”. drdobbs.com. 4 July 2010閲覧。
- ^ Shelly, Asaf (22 August 2008). “Flaws of Object Oriented Modeling”. Intel Software Network. 4 July 2010閲覧。
- ^ James, Justin (1 October 2007). “Multithreading is a verb not a noun”. techrepublic.com. 10 October 2007時点のオリジナルよりアーカイブ。4 July 2010閲覧。
- ^ Shelly, Asaf (22 August 2008). “HOW TO: Multicore Programming (Multiprocessing) Visual C++ Class Design Guidelines, Member Functions”. support.microsoft.com. 4 July 2010閲覧。
- ^ Robert Harper (17 April 2011). “Some thoughts on teaching FP”. Existential Type Blog. 5 December 2011閲覧。
- ^ Wirfs-Brock, Rebecca; Wilkerson, Brian (1989). “Object-Oriented Design: A Responsibility-Driven Approach”. ACM SIGPLAN Notices 24 (10): 74. doi:10.1145/74878.74885.
- ^ https://wiki.c2.com/?MichaelFeathers
出典
[編集]- Kindler, E.; Krivy, I. (2011). Object-Oriented Simulation of systems with sophisticated control. International Journal of General Systems. pp. 313–343.
- Lewis, John; Loftus, William (2008). Java Software Solutions Foundations of Programming Design (6th ed.). Pearson Education Inc.. ISBN 978-0-321-53205-3
- Kay, Alan; Ram, Stefan (23 July 2003). "Dr. Alan Kay on the Meaning of "Object-Oriented Programming"". www.purl.org. 2022年8月15日閲覧。
- McCarthy, J.; Brayton, R.; Edwards, D.; Fox, P.; Hodes, L.; Luckham, D.; Maling, K.; Park, D. et al. (March 1960). LISP I Programmers Manual. ボストン, マサチューセッツ: Artificial Intelligence Group, en:M.I.T. Computation Center and Research Laboratory. p. 88f. オリジナルの17 July 2010時点におけるアーカイブ。 . "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"."
- 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 . "Object — a synonym for atomic symbol"
- 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). 17 July 2019閲覧。
- Ali, Junade (2016-09-28) (英語). Mastering PHP Design Patterns (1 ed.). Birmingham, England, UK: Packt Publishing Limited. ISBN 978-1-78588-713-0
- Nygaard, Kristen; Dahl, Ole-Johan (1978-08-01). “Development of the SIMULA languages”. ACM SIGPLAN Notices (Association for Computing Machinery) 13 (8): 245–272. doi:10.1145/960118.808391.
- Dahl, Ole Johan (2004). “The Birth of Object Orientation: The Simula Languages”. From Object-Orientation to Formal Methods. Lecture Notes in Computer Science. 2635. pp. 15–25. doi:10.1007/978-3-540-39993-3_3. ISBN 978-3-540-21366-6 22 October 2021閲覧。.
- Kay, Alan (1993-03-01). “The Early History of Smalltalk”. ACM SIGPLAN Notices (Association for Computing Machinery) 28 (3): 69–95. doi:10.1145/155360.155364.
- 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.
- Meyer, Bertrand (2009). Touch of Class: Learning to Program Well with Objects and Contracts. Springer Science & Business Media. pp. 329. Bibcode: 2009tclp.book.....M. ISBN 978-3-540-92144-8
関連項目
[編集]システム
[編集]- CADES
- Common Object Request Broker Architecture (CORBA)
- Distributed Component Object Model
- Distributed Data Management Architecture
- Jeroo