
オブジェクト指向プログラミング(OOP)は、オブジェクト[ 1 ](データと関数をカプセル化するソフトウェアエンティティ)に基づくプログラミングパラダイムです。OOPコンピュータプログラムは、互いに相互作用するオブジェクトで構成されます。[ 2 ] [ 3 ] OOP言語とは、オブジェクト指向プログラミング機能を提供する言語ですが、OOPに貢献する機能のセットは議論の余地があるため、言語をOOPとして分類すること、およびOOPをサポートする程度は議論の余地があります。パラダイムは相互に排他的ではないため、言語はマルチパラダイム(つまり、OOPだけでなく、複数のパラダイムに分類される)になる可能性があります。
OOP をサポートする注目すべき言語には、Ada、ActionScript、C++、Common Lisp、C#、Dart、Eiffel、Fortran 2003、Haxe、Java、[ 4 ] JavaScript、Kotlin、Logo、MATLAB、Objective-C、Object Pascal、Perl、PHP、Python、R、Raku、Ruby、Scala、SIMSCRIPT、Simula、Smalltalk、Swift、Vala 、 Visual Basic (.NET)などがあります。
プログラミングにおける「オブジェクト」の概念は、1950年代後半から1960年代初頭にかけてマサチューセッツ工科大学(MIT)の人工知能グループで始まりました。ここで「オブジェクト」とは、識別されたプロパティ(属性)を持つLISPのアトムを指していました。 [ 5 ] [ 6 ] もう1つの初期の例は、 1960年から1961年にかけてMITのIvan Sutherlandによって作成されたSketchpadです。Sutherlandは、技術レポートの用語集で、「オブジェクト」や「インスタンス」などの用語を定義しました(クラスの概念は「マスター」または「定義」でカバーされています)。ただし、グラフィカルなインタラクションに特化したものでした。[ 7 ]その後、1968年に、MIT版ALGOLプログラミング言語であるAED-0は、データ構造(「プレックス」)と手続きを結び付け、後に「メッセージ」、「メソッド」、「メンバ関数」と呼ばれるものを先取りしました。[ 8 ] [ 9 ]この時期には、データ抽象化やモジュール型プログラミング などのトピックがよく議論されていました。
一方、ノルウェーでは、1961年から1967年にかけてSimulaが開発されました。 [ 8 ] Simulaは、クラス、継承、動的バインディングなどの重要なオブジェクト指向の概念を導入しました。[ 10 ] Simulaは主に、貨物港を通過する船舶とその内容物の移動など、物理モデリング に携わる研究者によって使用されました。 [ 10 ] Simulaは、オブジェクト指向言語の主要な機能とフレームワークを備えた最初の言語として一般的に認められています。[ 11 ]
私は、オブジェクトを生物学的細胞やネットワーク上の個々のコンピュータのようなものと考え、メッセージによってのみ通信できるものとしました(そのため、メッセージングは最初期に登場しました。プログラミング言語でメッセージングを効率的に、かつ実用的なものにする方法を見つけるまでには時間がかかりました)。
MITとSimulaの両方の影響を受け、アラン・ケイは1966年11月に独自のアイデアの開発を始めました。彼はその後、影響力のあるOOP言語であるSmalltalkを作成しました。1967年までに、ケイはすでに会話の中で「オブジェクト指向プログラミング」という用語を使用していました。[ 1 ]ケイはOOPの「父」と呼ばれることもありますが、[ 12 ]彼のアイデアはOOPが一般的に理解されている方法とは異なり、コンピュータ科学界が彼の概念を採用しなかったことを示唆しています。[ 1 ]バーバラ・リスコフ が共同執筆した1976年のMITのメモには、Simula 67、CLU、Alphardがオブジェクト指向言語として挙げられていますが、Smalltalkについては言及されていません。 [ 13 ]
1970年代、Smalltalkプログラミング言語の最初のバージョンは、 Alan Kay、Dan Ingalls、Adele GoldbergによってXerox PARCで開発されました。Smalltalk-72は、言語レベルでのオブジェクトの使用とグラフィカルな開発環境で注目されました。[ 14 ] Smalltalkは完全に動的なシステムであり、ユーザーは作業しながらクラスを作成および変更することができました。[ 15 ]オブジェクト指向プログラミングの理論の多くは、多重継承など、Smalltalkのコンテキストで開発されました。[ 16 ]
1970年代後半から1980年代にかけて、OOPが注目を集めるようになりました。オブジェクト指向LispであるFlavorsは1979年から開発され、多重継承とミックスインが導入されました。[ 17 ] 1981年8月、Byte MagazineはSmalltalkとOOPを取り上げ、これらのアイデアを幅広い読者に紹介しました。[ 18 ] Interlisp -DのオブジェクトシステムであるLOOPSは、SmalltalkとFlavorsの影響を受けており、1982年にそれに関する論文が発表されました。[ 19 ] 1986年には、オブジェクト指向プログラミング、システム、言語、アプリケーションに関する最初の会議(OOPSLA)が開催され、1,000人が参加しました。この会議は、Lispオブジェクトシステムを統合する取り組みの始まりとなり、最終的にCommon Lisp Object Systemが誕生しました。1980年代には、メモリ内のオブジェクトのハードウェアサポートを含むプロセッサアーキテクチャを設計する試みがいくつかありましたが、これらは成功しませんでした。例としては、Intel iAPX 432やLinn Smart Rekursivなどがあります。
1980年代半ばには、Objective-C、C++、Eiffel言語などの新しいオブジェクト指向言語が登場しました。Objective-Cは、 ITT Inc.でSmalltalkを使用していたBrad Coxによって開発されました。Bjarne Stroustrupは、博士論文でSimulaを使用した経験に基づいてC++を作成しました。[ 14 ] Bertrand Meyerは、契約による設計アプローチを使用してソフトウェアの品質に焦点を当てたEiffel言語の最初の設計を1985年に作成しました。[ 20 ]
1990年代には、OOPがプログラミングの主流となり、特に多くの言語がそれをサポートするようになった。これにはVisual FoxPro 3.0 [ 21 ] [ 22 ] C++ [ 23 ]、およびDelphiが含まれる。OOPは、ボタン、メニュー、その他の要素にオブジェクトを使用するグラフィカルユーザーインターフェースの台頭により、さらに人気が高まった。よく知られた例の1つは、 macOSで使用され、 Objective-Cで記述されているAppleのCocoaフレームワークである。OOPツールキットは、イベント駆動型プログラミングの人気も高めた。
チューリッヒ工科大学(ETH Zürich)において、ニクラウス・ヴィルトとその同僚たちは、オブジェクト指向プログラミング(OOP)への新たなアプローチを生み出した。Modula -2(1978年)とOberon(1987年)は、モジュール境界を越えたオブジェクト指向、クラス、型チェックに対する独自のアプローチを採用している。ヴィルトの設計では、継承は一見して明らかではない。なぜなら、彼の命名法は逆方向を向いているからである。それは型拡張と呼ばれ、視点は親から継承者へと向けられている。
オブジェクト指向プログラミングが普及する以前に開発された多くのプログラミング言語は、 Ada、BASIC、Fortran、Pascal、COBOLなどを含め、オブジェクト指向機能が追加されてきた。
言語によって提供されるOOP機能は異なります。以下に、OOP言語の一般的な機能を示します。[ 24 ] [ 25 ] [ 26 ] [ 27 ] OOPには明確で合意された定義がないため、関係プログラミングなどの他のスタイルとOOPを比較することは困難です。 [ 28 ]
情報隠蔽とカプセル化は、いくつかの関連する概念を指す場合がある。
Java などのプログラミング言語では、可視性キーワード (privateおよびpublic) による情報隠蔽が提供されています。[ 30 ] Python などの言語では可視性機能は提供されていませんが、開発者はプライベートメンバ名をアンダースコアで始めるなどの慣例に従う場合があります。中間レベルのアクセスも存在し、Java のprotectedキーワード (同じクラスとそのサブクラスからのアクセスは許可されますが、異なるクラスのオブジェクトからのアクセスは許可されません) や、internalC#、Swift、Kotlin のキーワード (同じモジュール内のファイルへのアクセスを制限します) などがあります。[ 31 ]
情報隠蔽とデータ抽象化の支持者は、これによってコードの再利用が容易になり、現実世界の状況を直感的に表現できると主張している。[ 32 ] [ 33 ]しかし、OOP は可読性やモジュール性を向上させないと主張する人もいる。[ 34 ] [ 35 ]エリック・S・レイモンドは、OOP 言語は透明性を損なう厚い階層のプログラムを助長する傾向があると述べている。[ 36 ]レイモンドは、これをUnixやC言語で採用されているアプローチと比較して好ましくないとしている。[ 36 ]
SOLIDには、クラスと関数は「拡張に対してはオープンだが、変更に対してはクローズドであるべき」というオープン/クローズドの原則が含まれています。Luca Cardelliは、OOP言語は「クラスの拡張と変更に関して極めて劣悪なモジュール性特性」を持ち、極めて複雑になりがちであると述べています。[ 34 ]後者の点は、 Erlangの主要発明者であるJoe Armstrongによっても繰り返されており、彼は次のように述べていると引用されています。 [ 35 ]
オブジェクト指向言語の問題点は、暗黙のうちに環境情報をすべて持ち歩いてしまうことです。バナナが欲しかったのに、バナナを持ったゴリラとジャングル全体が手に入ってしまったようなものです。
レオ・ブロディは、情報隠蔽は重複コードにつながる可能性があると述べている[ 37 ]。これはソフトウェア開発の「繰り返しを避ける」ルールに反する[ 38 ] 。
継承はクラスまたはプロトタイプを介してサポートされます。これらは違いがありますが、オブジェクトやインスタンスなどの類似した用語を使用します。
クラスベースプログラミング(最も一般的なオブジェクト指向プログラミング)では、オブジェクトはクラスのインスタンスです。クラスはデータ(変数)とメソッド(ロジック)を定義します。オブジェクトはコンストラクタを介して作成されます。クラスのすべてのインスタンスは、同じ変数とメソッドのセットを持ちます。要素には以下が含まれます。
クラスは他のクラスから継承することができ、これによりクラスの階層構造が構築されます。これは、サブクラスがスーパークラスから継承するケースです。たとえば、クラスは、Employee オブジェクトに の変数を与えるクラスEmployeeから継承することができます。サブクラスは、スーパークラスに影響を与えない変数やメソッドを追加できます。ほとんどの言語では、サブクラスがスーパークラスのメソッドをオーバーライドすることもできます。一部の言語では、クラスが複数のクラスから継承できる多重継承がサポートされており、他の言語では同様にミックスインやトレイトがサポートされています。たとえば、UnicodeConversionMixin というミックスインは、FileReader クラスと WebPageScraper クラスの両方に unicode_to_ascii() メソッドを追加できます。PersonPerson
抽象クラスはオブジェクトとして直接インスタンス化することはできません。スーパークラスとしてのみ使用されます。
その他のクラスは、クラス変数とメソッドのみを含むユーティリティクラスであり、インスタンス化やサブクラス化を意図していません。[ 39 ]
プロトタイプベースのプログラミングでは、クラスの概念を提供する代わりに、オブジェクトはプロトタイプまたは親と呼ばれる別のオブジェクトにリンクされます。Self では、オブジェクトは複数の親を持つ場合も、親を持たない場合もありますが[ 40 ]、最も人気のあるプロトタイプベースの言語であるJavaScriptでは、オブジェクトはプロトタイプが null である基本オブジェクトまで、正確に 1 つのプロトタイプ リンクを持ちます。
プロトタイプは、新しいオブジェクトのモデルとして機能します。たとえば、オブジェクト がある場合、プロトタイプの特性を共有する2 つのオブジェクトとfruitを作成できます。プロトタイプベースの言語では、オブジェクトが独自のプロパティを持つことも可能なので、オブジェクト には属性 がある一方で、オブジェクトや には属性がないといったことも考えられます。appleorangefruitapplesugar_contentorangefruit
すべてのオブジェクト指向プログラミング言語では、オブジェクト合成によって、オブジェクトは他のオブジェクトを含むことができます。たとえば、オブジェクトは、オブジェクトと、やなどの他の情報Employeeを含むことができます。合成は、「従業員は住所を持っている」のような「has-a」関係です。Go などの一部の言語は、継承をサポートしていません。[ 41 ]代わりに、親子関係ではなく、より小さな部分を使用してオブジェクトを構築する「継承よりも合成」を推奨しています。たとえば、Employee クラスは Person クラスから継承する代わりに、単に Person オブジェクトを含むことができます。これにより、Employee クラスは、プログラムの他の部分に公開する Person の量を制御できます。委譲は、継承の代替として使用できるもう 1 つの言語機能です。Addressnameposition
プログラマーの間では、継承について様々な意見がある。C++ の作者であるビャルネ・ストロヴストルップは、継承なしでも OOP は可能だと述べている。[ 42 ]ロブ・パイクは、継承はよりシンプルな解決策ではなく、複雑な階層構造を生み出すとして批判している。[ 43 ]
人々は、あるクラスが別のクラスを継承する場合、サブクラスは元のクラスのより具体的なバージョンであると考えることが多い。これは、サブクラスのオブジェクトが元のクラスのオブジェクトを問題なく置き換えることができるというプログラムセマンティクスを前提としている。この概念は、振る舞いサブタイピング、より具体的にはリスコフ置換原理として知られている。
しかし、これは必ずしも真実ではありません。特に、作成後に変更される可変オブジェクトを許容するプログラミング言語ではなおさらです。実際、オブジェクト指向プログラミング言語の型チェッカーによって強制されるサブタイプ多相性は、ほとんどすべてのコンテキストにおいて、振る舞いのサブタイピングを保証することはできません。例えば、円と楕円の問題は、オブジェクト指向プログラミングの継承の概念を用いて扱うのが非常に難しいことで知られています。振る舞いのサブタイピングは一般的に決定不能であるため、コンパイラによって容易に実装することはできません。そのため、プログラマは、プログラミング言語自体では検出できないようなミスを避けるために、クラス階層を慎重に設計する必要があります。
メソッドは動的ディスパッチによって呼び出されることがあり、その場合、メソッドはコンパイル時ではなく実行時に選択されます。メソッドの選択が複数の種類のオブジェクト(パラメータとして渡される他のオブジェクトなど)に依存する場合、それは多重ディスパッチと呼ばれます。この文脈では、メソッド呼び出しはメッセージパッシングとも呼ばれ、メソッド名とその入力は、オブジェクトが処理するためのメッセージのようなものです。[ 44 ]
動的ディスパッチは継承と連携して動作します。オブジェクトに要求されたメソッドがない場合、親クラス(委譲)を検索し、一致するメソッドを見つけるためにチェーンを遡ります。
OOPにおけるポリモーフィズムとは、サブタイピングまたはサブタイプポリモーフィズムを指し、関数が特定のインターフェースで動作し、異なるクラスのエンティティを統一的に操作できることを意味します。[ 45 ]
例えば、プログラムに円と四角形の2つの図形があるとします。どちらも「Shape」という共通クラスに属しています。それぞれの図形には、描画方法が異なります。サブタイプ多態性のおかげで、プログラムは各図形の型を知る必要がなく、各図形に対して「Draw」メソッドを呼び出すだけで済みます。プログラミング言語のランタイムが、各図形に対して適切なバージョンの「Draw」メソッドが実行されるようにします。各図形の詳細はそれぞれのクラス内で処理されるため、コードがよりシンプルかつ整理され、関心の分離が強力になります。
オブジェクトのメソッドは、そのオブジェクトのデータにアクセスできます。多くのプログラミング言語では、現在のオブジェクトを参照するために、` this`thisや `this`のような特別な単語を使用します。オープン再帰をサポートする言語では、オブジェクト内のメソッドは、この特別な単語を使用して、同じオブジェクト内の他のメソッド(自身を含む)を呼び出すことができます。これにより、あるクラスのメソッドが、サブクラスで後から定義された別のメソッドを呼び出すことが可能になります。これは、遅延バインディングと呼ばれる機能です。self
デザインパターンは、ソフトウェア設計における問題解決のための一般的な手法です。デザインパターンの中には、特にオブジェクト指向プログラミング(OOP)に役立つものがあり、デザインパターンは通常、OOPの文脈で導入されます。
オブジェクトは、現実世界の事物やプロセスをデジタル形式で表現することもあります。[ 46 ]例えば、グラフィックス プログラムにはcircle、、、squareなどのオブジェクトがあるかもしれませんmenu。オンライン ショッピング システムにはshopping cart、、、、customerなどのオブジェクトがあるかもしれませんproduct。ニクラウス ヴィルトは、「このパラダイム [OOP] は現実世界のシステムの構造を忠実に反映しており、複雑な動作を持つ複雑なシステムをモデル化するのに適しています」と述べています。[ 47 ]
しかし、多くの場合、オブジェクトは、開いているファイルや単位変換器のような抽象的な実体を表します。OOP によって現実世界を正確にコピーすることが容易になる、あるいはそうすること自体が必要であるという点については、誰もが同意しているわけではありません。ボブ・マーティンは、クラスはソフトウェアであるため、その関係はそれが表す現実世界の関係と一致しないと指摘しています。[ 48 ]ベルトラン・メイヤーは、プログラムは世界のモデルではなく、世界の何らかの部分のモデルであると主張しています。「現実は二度隔てたいとこである」。[ 49 ]スティーブ・イェッゲは、関数型プログラミングとは逆に、自然言語には、アクション (メソッド) の前に物事 (オブジェクト) に名前を付けるという OOP のアプローチが欠けていると指摘しています。 [ 50 ]このため、OOP によるソリューションは、手続き型プログラミングで書かれたものよりも複雑になる可能性があります。[ 51 ]
以下は、OOPオブジェクトのための注目すべきソフトウェア設計パターンです。[ 52 ]
operator())よくあるアンチパターンの一つに「ゴッドオブジェクト」がある。これは、知りすぎたり、やりすぎたりするオブジェクトのことだ。
『デザインパターン:再利用可能なオブジェクト指向ソフトウェアの要素』は、1994年にエーリッヒ・ガンマ、リチャード・ヘルム、ラルフ・ジョンソン、ジョン・ヴリシデスという4人の著者によって出版された有名な書籍です。彼らはしばしば「4人組」と呼ばれています。本書では、オブジェクト指向プログラミングの長所と短所について論じ、プログラミングの問題を解決するための23の一般的な方法を解説しています。
これらの解決策は「デザインパターン」と呼ばれ、以下の3種類に分類されます。
オブジェクト指向プログラミング( OOP)とリレーショナルデータベース管理システム(RDBMS)は、今日のソフトウェア開発において広く利用されています。しかし、リレーショナルデータベースはオブジェクトを直接格納しないため、両者を併用する際に課題が生じます。この問題は、オブジェクト・リレーショナルインピーダンスミスマッチと呼ばれています。
この問題を解決するために、開発者はさまざまな方法を使用しますが、どれも完璧ではありません。[ 53 ]最も一般的な解決策の 1 つはオブジェクトリレーショナルマッピング(ORM) であり、オブジェクト指向プログラムをリレーショナルデータベースに接続するのに役立ちます。ORM ツールの例としては、Visual FoxPro、Java Data Objects、Ruby on Rails ActiveRecord などがあります。
オブジェクトデータベースと呼ばれる一部のデータベースは、オブジェクト指向プログラミング(OOP)に対応するように設計されています。しかし、リレーショナルデータベースほど普及も成功もしていません。
DateとDarwenは、RDBMSをサポートするためにカスタマイズ可能な型システムの一種としてOOPを使用する理論的基盤を提案したが、他のオブジェクトへのポインタを含むオブジェクトは禁止されている。[ 54 ]
責任主導型設計では、クラスは、実行する必要のあることと共有する情報に基づいて、契約の形で構築されます。これは、クラスが保存する必要のあるデータに基づいて構築されるデータ駆動型設計とは異なります。責任主導型設計の創始者であるWirfs-BrockとWilkersonによると、責任主導型設計の方が優れたアプローチです。[ 55 ]
SOLIDとは、マイケル・フェザーズによって考案された、優れたソフトウェアを設計するための5つのルールである。
GRASP(General Responsibility Assignment Software Patterns)は、クレイグ・ラーマンによって作成されたソフトウェア設計ルールのもう1つのセットで、開発者がプログラムのさまざまな部分に責任を割り当てるのに役立ちます。[ 56 ]
研究者たちは、OOP のセマンティクスを形式的に定義しようと試みてきた。継承は、特にオープン再帰とカプセル化された状態の間の相互作用において困難を伴う。研究者たちは、 OOP の本質的な機能を組み込むために再帰型と共代数的データ型を使用してきた。[ 57 ] Abadi と Cardelli は、可変オブジェクトを扱うSystem F <:のいくつかの拡張を定義し、サブタイプ多相性とパラメトリック多相性(ジェネリクス) の両方を可能にし、多くの OOP の概念と構成要素を形式的にモデル化することができた。[ 58 ] Java などのオブジェクト指向プログラミング言語の静的解析は決して自明ではないが、成熟した分野であり、[ 59 ]いくつかの商用ツールが存在する。[ 60 ]

C++、Java、Pythonなどの多くの人気プログラミング言語はOOPを使用しています。過去にはOOPは広く受け入れられていましたが[ 61 ]、最近では一部のプログラマーがそれを批判し、代わりに関数型プログラミングを好んでいます[ 62 ]。Potokらによる研究では、OOPと手続き型プログラミングの生産性に大きな違いはないことがわかりました[ 63 ] 。
OOP はアルゴリズムやデータ構造よりもオブジェクトの使用に重点を置きすぎていると考える人もいます。[ 64 ] [ 65 ]例えば、プログラマーのRob Pike は、OOP によってプログラマーが合成よりも型階層について考えるようになる可能性があると指摘しました。[ 66 ]彼は OOP を「コンピューティングのローマ数字」と呼んでいます。 [ 67 ] Clojureの作成者であるRich Hickey は、特に時間の経過とともに変化する現実世界の事物を表現する場合、OOP は過度に単純化されていると述べています。[ 65 ] Alexander Stepanov は、OOP はすべてを単一の型に収めようとするため、制限がある可能性があると述べています。彼は、ジェネリック プログラミングのように、複数の型にまたがるインターフェースのファミリーであるマルチソート代数が必要になる場合があると主張しました。Stepanov はまた、すべてを「オブジェクト」と呼ぶことは理解を深めることにはあまり役立たないと述べています。[ 64 ]
OOP は、コードの再利用と保守を容易にするために作成されました。[ 68 ]しかし、プログラムの命令の流れを明確に示すようには設計されていませんでした。それはコンパイラに任されていました。コンピュータが並列処理やマルチスレッドをより多く使用するようになると、命令の流れを理解して制御することがより重要になりました。これは OOP では難しいことです。[ 69 ] [ 70 ] [ 71 ] [ 72 ]
ポール・グラハムは、平均的なプログラマーの大規模なチームを管理するのに役立つため、大企業はOOPを好むと考えている。彼は、OOPは構造を追加し、一人が重大なミスを犯すことを難しくするが、同時に優秀なプログラマーを制約すると主張する。[ 73 ] Unixプログラマーでありオープンソースソフトウェアの提唱者であるエリック・S・レイモンドは、OOPはプログラムを書く最良の方法ではないと主張する。[ 36 ]
リチャード・フェルドマンは、OOP の機能は一部の言語の整理に役立ったが、その人気の理由は他にあると述べている。[ 74 ]ローレンス・クルブナーは、OOP は関数型プログラミングなどの他のスタイルと比べて特別な利点はなく、コーディングを複雑にする可能性があると主張している。[ 75 ]ルカ・カルデッリは、OOP は手続き型プログラミングよりも遅く、コンパイルに時間がかかると述べている。[ 34 ]
。 MIT の現地語では、アトミック シンボルの連想リストは「プロパティ リスト」とも呼ばれ、アトミック シンボルは「オブジェクト」と呼ばれることもあります。
– 原子記号の同義語
{{cite book}}ISBN /日付の不一致(ヘルプ){{cite news}}: CS1 maint: url-status (リンク)には型とメソッドがあり、オブジェクト指向スタイルのプログラミングが可能ですが、型階層はありません。
ポリモーフィズム – 異なる型のエンティティに単一のインターフェースを提供する。
オブジェクト指向開発アプローチの最大の強みは、現実世界のモデルを捉えるメカニズムを提供する点にあると言えるでしょう。
オブジェクト指向プログラミングは広く受け入れられているプログラミングパラダイムである。