「オブジェクト指向プログラミング」の版間の差分

削除された内容 追加された内容
G000001 (会話 | 投稿記録)
RnTknn (会話) による ID:86074638 の版を取り消し RnTkmさんのコメントでの指摘等がほぼ消える等、巻き戻り?が発生しているようなので復帰しました。また、RnTknnさん&つもりやもりさん過去記述分⇔RnTkmさんコメントでの増減が主なようですが、RnTknnさんはRnTkmさんと別人ということでよろしいでしょうか(既にご指摘はあるようですが)
タグ: 取り消し 差し戻し済み
RnTknn (会話 | 投稿記録)
この編集は御指摘頂いた数々の誤りと問題点と冗長さを直したものですのでどうか戻さないでください。自分の編集に問題があるのは重々承知ですが、ここでは可能な限り正しい記述にしたいのでどうかお願いします。自分の誤りを残したままにするのは心苦しいのでどうかお願い致します。
タグ: 手動差し戻し 差し戻し済み
18行目:
広く使われているプログラミング言語の多く(C++、Java、Pythonなど)は、[[マルチパラダイムプログラミング言語|マルチパラダイム]]であるが、程度の差はあれ、オブジェクト指向プログラミングをサポートしており、大抵は[[命令型プログラミング|命令型]]や[[手続き型プログラミング]]との組み合わせで用いられる。
主なオブジェクト指向言語には次のようなものが挙げられる:
[[Java]]、[[C++]]、[[C_Sharp|C#]]、[[Python]]、[[R言語|R]]、[[PHP (プログラミング言語)|PHP]]、[[Visual_Basic_.NET]]、[[JavaScript]]、[[Ruby]]、[[Perl]]、[[:en:SIMSCRIPT|SIMSCRIPT(英語版)]]、[[Object Pascal]]、[[Objective-C]]、[[Dart]]、[[Swift (プログラミング言語)|Swift]]、[[Scala]]、[[Kotlin]]、[[Common Lisp]]、[[MATLAB]]、そして[[Smalltalk]]。<!-- 以上まで、ほぼ [[en:Object-oriented programming]] oldid=1047374345 の翻訳 --><!-- 以下より文末までほぼ出典なしの記述(出典なしの記述が大量に続いている、ということが以前より懸念されています。詳細は議論ノートをご参照ください -->
 
<!-- 以上まで、ほぼ [[en:Object-oriented programming]] oldid=1047374345 の翻訳 -->
 
<!-- 以下より文末までほぼ出典なしの記述(出典なしの記述が大量に続いている、ということが以前より懸念されています。詳細は議論ノートをご参照ください -->
 
== 歴史 ==
{{独自研究|date=2021-10}}
 
'''[[オブジェクト指向]]'''という言葉自体は、計算機科学者[[アラン・ケイ]]によって作り出されている。[[Simula]]言語などにインスパイアされたケイが1967年頃に口にしたと伝えられるこの造語は<ref name="造語">“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".”[http://www.purl.org/stefan_ram/pub/doc_kay_oop_en%7CDr. Alan Kay on the Meaning of “Object-Oriented Programming”]</ref>、彼が1972年から開発を始めた言語[[Smalltalk]]の設計を説明する過程で明確な用語として発信され、1981年頃から知名度を得るようになった。80年代半ばになるとオブジェクト指向の解釈は、元々のアラン・ケイによる[[Smalltalk]]の様式と、1983年に計算機科学者[[ビャーネ・ストロヴストルップ]]が公開した[[C++]]の様式に二分された。前者では[[メッセージング]]という概念が基礎にされ、後者では[[Simula|Simula67]]由来の諸機能を加えた[[抽象データ型]]のスーパーセットが基礎にされていた。現在ではC++の様式がオブジェクト指向の標準になっている。
 
=== Simula以前 ===
 
1954年に初の[[高水準言語]]・[[FORTRAN]]が登場すると、開発効率の劇的な向上と共にソフトウェア要求度も自然と高まりを見せてプログラム規模の急速な拡大が始まった。それに対応するために肥大化したメインルーチンを[[サブルーチン]]に分割する手法と、[[スパゲティプログラム|スパゲティ化]]した[[Goto文|goto命令]]を[[制御構造|制御フロー構文]]に置き換える手法が編み出され、これらは1960年に公開された言語「[[ALGOL|ALGOL60]]」で形式化された。当時のALGOLは[[アルゴリズム]]記述の一つの模範形と見なされたが、それと並行して北欧を中心にした計算機科学者たちはより大局的な観点によるプログラム開発技法の研究を進めていた。
 
=== Simulaの開発(1962 - 72) ===
1962年、ノルウェー計算センターで[[モンテカルロ法]]シミュレーションを運用していた計算機科学者[[クリステン・ニゴール]]は[[ALGOL|ALGOL60]]を土台にしてProcessと呼ばれる[[コルーチン]]機構を加えたプログラミング言語「[[Simula]]」を制作し、続けてその拡張にも取り組んだ。ニゴールの同僚で、1963年にSimulaを[[メインフレーム|汎用機]][[UNIVAC I|UNIVAC]]系統上で運用できるように実装した計算機科学者[[オルヨハン・ダール]]は、Processにローカル変数構造を共有する手続き(サブルーチン)を加えてパッケージ化する言語仕様を考案し、これは任意の変数と手続きをまとめる[[モジュール|プログラムモジュール]]と同類の機能になった。程なくしてALGOL60コンパイラに準拠していての限界を悟ったニゴールとダールは、1965年からSimulaを一から再設計するように方針転換した。その過程で彼らは、計算機科学者[[アントニー・ホーア]]が考案して1962年のSIMSCRIPT([[FORTRAN]]用のスクリプト)に実装していたRecord Classを参考にしている。Record Classはソースコード水準の抽象記号を、各[[メインフレーム|汎用機]]に準拠した[[マシンコード]]水準の実装符号に落とし込む段階的データ構造のプログラム概念であった。これをモデルにした[[継承 (プログラミング)|継承]]と、その継承構造を利用した仮想手続き(仮想関数)の仕組みも考案され、上述のパッケージ化されたProcess(モジュール)に継承と仮想手続きの両機能を加えたものを「[[クラス (コンピュータ)|クラス]]」と定義し、クラスをメモリに展開したものを「[[オブジェクト (プログラミング)|オブジェクト]]」と定義する言語仕様がまとまり、1967年に「[[Simula|Simula67]]」が初公開された。オブジェクトという用語は、[[MIT]]の計算機科学者[[アイバン・サザランド]]が1963年に開発した[[Sketchpad]]の設計上にあったObjectが先例であった。[[Sketchpad]]は[[CAD]]と[[GUI]]の原点として知られており、後述の[[Smalltalk]]のモチーフの一つにもなっている。Simula67コンパイラはまず汎用機[[UNIVAC I|UNIVAC]]上で運用され、翌年から汎用機[[バロース B5000|バロースB5500]]などでも稼働されて北欧、ドイツ、ソ連の各研究機関へと広まり、1972年には[[IBMメインフレーム|IBM汎用機]][[System/360]]などにも導入されて北米全土にも広まった。その主な用途は離散事象および物理シミュレーションであった。
 
=== 構造化プログラミングの提唱(1969 - 75) ===
49 ⟶ 39行目:
[[Simula]]を研究対象にしていた[[ベル研究所|AT&Tベル研究所]]の計算機科学者[[ビャーネ・ストロヴストルップ]]は、1979年からクラス付きC言語の制作に取り組み、1983年に「[[C++]]」を公開した。C++で実装された[[クラス (コンピュータ)|クラス]]は、Simula由来の[[継承 (プログラミング)|継承]]と仮想関数に加えて、段階的な[[レキシカルスコープ]]の概念をクラス構造に応用した[[アクセスコントロール]]を備えていた。C++で確立されたアクセスコントロールは情報隠蔽によるデータ抽象を提示したが、コードスタイル上ほとんどザル化されており、その理由からストロヴストルップ自身もC++は正しくない(''not just'')オブジェクト指向言語であると明言している。1986年にソフトウェア技術者[[バートランド・メイヤー]]が制作した「[[Eiffel]]」の方は、正しいオブジェクト指向を標榜してクラスのデータ抽象を遵守させるコードスタイルが導入されていた。クラスメンバ(フィーチャー)は属性/手続き/関数の三種構成で、手続きで属性を変更して関数で属性を閲覧するという形式に限定されており、これは[[抽象データ型]]に忠実な実装であった。アクセスコントロールはC++のとは異なるクラス指名方式にされ、仮想関数機能は延期手続き/関数として実装された。
 
1986年から[[Association for Computing Machinery|ACM]]が[[OOPSLA]]を年度開催するようになり、オブジェクト指向は従来の[[構造化プログラミング|構造化開発]]に代わる技術として明確に意識され始めた。OOPSLAのプログラミング言語セクションでは、[[抽象データ型]]を基礎にした[[クラス (コンピュータ)|クラス]]・パラダイムが主要テーマにされ、それを標準化するための数々のトピックが議題に上げられている。[[モジュール|モジュール分割]]、[[抽象化 (計算機科学)|抽象化]]、[[再利用|再利用性]]、[[継承 (プログラミング)|階層構造]]、複合構成、情報隠蔽、実行時多態、[[動的束縛]]、[[総称型]]、[[永続性]]、[[並行性]]、[[ガベージコレクション|自動メモリ管理]]といったものがそうであり、参画した識者たちによる寄稿、出版、講演を通して世間にも広められた。そうした潮流の中で[[ビャーネ・ストロヴストルップ|ストロヴストルップ]]はデータ抽象の重要性を訴え、[[バーバラ・リスコフ|リスコフ]]は[[上位概念、下位概念、同位概念および同一概念|基底と派生]]に分けたデータ抽象の階層構造の連結関係([[リスコフの置換原則|置換原則]])について提言した。[[契約による設計]]と[[開放/閉鎖原則|開放閉鎖原則]]を提唱する[[バートランド・メイヤー|メイヤー]]が1988年に刊行した『オブジェクト指向ソフトウェア構築』によるEiffel式のクラス理論は高く評価され、Eiffelを現行の模範形とする声も多く上がった。ただしこれは学術寄りの意見でもあったようで、世間のプログラマの間では厳格なEiffelよりも、柔軟で融通の利くC++の人気の方が高まっていた。他方で[[アラン・ケイ]]のメッセージ・メタファに忠実であろうとする動きもあり、1984年に制作された「[[Objective-C]]」はC言語をSmalltalk方向に拡張してメッセージ式を平易化した言語であった。1987年に[[パロアルト研究所]]で誕生した「[[Self]]」は、Smalltalkの[[クラスベース]]設計をより柔軟に平易化した[[プロトタイプベース]]を編み出している。これらのメッセージレシーバーは、静的メソッド選択優先の動的ディスパッチ機構という方式でほぼ形式化された。メッセージレシーバーの仕組みは[[遠隔手続き呼出し]]や[[Object Request Broker|オブジェクト要求ブローカー]]の実装に適していたので、[[分散システム]]とオブジェクト指向の親和性を認識させることになった
 
=== コンポーネントとネットワーク(1989 - 97) ===
ネットワーク技術の発展に連れて、データとメソッドの複合体であるオブジェクトの概念は、[[分散システム]]構築のための基礎要素としての適性を特に見出される事になり、[[IBM|IBM社]]、[[Apple|Apple社]]、[[サン・マイクロシステムズ|サン社]]などが1989年に共同設立した[[Object Management Group|OMG]]は、企業システムネットワーク向け分散オブジェクトプログラミング規格となる[[CORBA]]を1991年に発表した。その前年に[[マイクロソフト|マイクロソフト社]]は[[ウェブアプリケーション]]向けの分散オブジェクトプログラミング技術となる[[OLE]]を発表し、1993年には[[Component Object Model|COM]]と称する[[ソフトウェアコンポーネント]]仕様へと整備した。この[[Component Object Model|COM]]の利用を眼目にしてリリースされた「[[Microsoft Visual C++|Visual C++]]」「[[Visual Basic]]」は[[World Wide Web|ウェブ]]時代の新しいプログラミング様式を普及させる先駆になった。この頃にデータ抽象、データ隠蔽、[[アクセスコントロール]]および[[インタフェース (抽象型)|インターフェース]]によるプログラムの抽象化は、総じて[[カプセル化]]の概念でまとめられるようになった。クラスの[[継承 (プログラミング)|継承]]が最もオブジェクト指向らしい機能と見なされていたのが当時の特徴であった。継承構造を利用した振る舞いサブタイピング及び動的ディスパッチは[[多態性]]という用語に包括された。こうしていわゆるオブジェクト指向の三大要素がやや漠然と確立されている。1996年にサン社がリリースした「[[Java]]」は三大要素が強く意識された[[クラスベース]]であり、その中の分散オブジェクト技術は[[JavaBeans|Beans]]と呼ばれた。類似の技術としてApple社も[[MacOS]]上で[[Objective-C]]などから扱える[[Cocoa]]を開発している。また、1994年から96年にかけて「[[Python]]」「[[Ruby]]」「[[JavaScript]]」といったオブジェクト指向スクリプト言語がリリースされ、従来の[[静的型付け]]に対する[[動的型付け]]と、[[クラスベース]]に対する新しい[[プロトタイプベース]]の認知度を高めている。
 
抽象化を旨とするオブジェクト指向ではそのプログラミング自体の抽象化も積極的に推進されている。80年代後半から立ち上げられた[[オブジェクト指向分析設計|オブジェクト指向分析]](OOA)や[[オブジェクト指向設計]](OOD)の各手法から導き出される[[コンセプトモデル|概念モデル]]を、多角的に[[フローチャート|チャート化]]ないし[[ダイアグラム|ダイアグラム化]]するための数々のオブジェクト指向開発方法論が[[OOPSLA]]界隈の識者たちから発表されるようになり、そこで用いられる[[形式言語]]は{{仮リンク|オブジェクトモデリング言語|en|Object-modeling language}}と呼ばれた。これはプログラミングのためのプロトタイプ(ひな型)として重視され、オブジェクト指向では[[モデリング言語]]と[[プログラミング言語]]が並んでソフトウェア開発の両輪になった。1994年にモデリング言語による[[ギャング・オブ・フォー (情報工学)|GOF]][[デザインパターン (ソフトウェア)|デザインパターン]]が初回発表され、これはオブジェクト指向教育で非常に重視されるようになった。1995年にモデリング言語の標準化を企図した[[統一モデリング言語|UML]]が[[OOPSLA]]で初回発表され、1997年に[[Object Management Group|OMG]]の標準モデリング言語として採用された。同年に[[デザインパターン (ソフトウェア)|デザインパターン]]を帰納的に分析して九原則にまとめた[[GRASP]]が発表されている
 
== 特徴 ==
{{独自研究|date=2021-04}}
OOPでは[[クラスベース]]と呼ばれるスタイルが標準にされている。他に[[プロトタイプベース]]と呼ばれる後発のスタイルもあるが、こちらは少数派である。クラスベースのOOP言語は、[[Smalltalk]]様式と[[C++]]様式で二分大別されており{{要出典|date=2021年10月|title=二分されているというのは正しいのかもしれないが、「C++様式」という用語が一般的なのか怪しいのと、出典は要る。 それとここで言う C++様式 かつ 動的型付け である言語の例は?}}、C++様式の方がずっと多数派である。C++様式は、[[静的型付け]]と[[動的型付け]]の分類で大別されている。それらの主な特徴を箇条書きするとこうなる。
 
* [[クラスベース]] - クラスのインスタンス化でオブジェクトを構築する。
** [[Smalltalk]]様式 - クラスとインスタンスの[[相対性]]を付与してオブジェクトを体系化している。動的型付け中心。[[メッセージパッシング]]による多態性。
** [[C++]]様式 - クラス(型)とインスタンス(値)<!--型付け値 ←怪しい用語-->に分離してオブジェクトを体系化している。{{仮リンク|動的ディスパッチ|en|Dynamic dispatch}}による多態性。
*** [[静的型付け]] - 実行時のオブジェラストの構成が基本的解釈(型チェックなど)を主にコンパイル時固定されている。
*** [[動的型付け]] - 実行時のオブジェラストの構成の変更が前提解釈(型チェックなど)を主されてい実行時にする。{{疑問点|date=2021年10月|title=動的型付けはそういう意味ではない}}
* [[プロトタイプベース]] - オブジェクトのクローンでオブジェクトを構築する。クラスとインスタンスの[[相対性]]をオブジェクトから撤廃して、プロトタイプでオブジェクトを体系化している。動的型付け中心。[[動的束縛|動的バインディング]]による多態性。
なお、場合によっては C言語などオブジェクト指向を支援しない言語でオブジェクト指向的なプログラミングが行われることもある<!-- それについての書籍があったはず -->。
 
本稿では最も標準的なクラスベースのC++様式の静的型付けを基準にして説明する。<!-- 動的型付けのオブジェクト指向言語もかなり使われているので疑問。 -->
 
なお、場合によっては C言語などオブジェクト指向を支援しない言語でオブジェクト指向的なプログラミングが行われることもある<!-- それについての書籍があったはず -->。
 
参考: <!-- [[クラスベース]]OOPの中心である[[クラス (コンピュータ)|クラス]]の実装様式を規定している以下の三項目は、 「クラスの実装様式」では意味がはっきりしない。-->
後述の「カプセル化」「継承」「ポリモーフィズム」の3項目は、<!-- 日本では -->「オブジェクト指向の三大要素」または「3大特徴」などと言われることもあるが、広く認められたものではないし、「オブジェクト指向プログラミングの特徴」なのか「オブジェクト指向言語に求められる機能」なのかという点も曖昧である。
<!-- 各要素の軽視重視と導入方法は言語別に様々である。 -->
 
=== クラスとインスタンス ===
OOPの要点である[[クラス (コンピュータ)|クラス]]は、[[データ構造]]とそれを扱うための操作・振る舞いをひとまとめにした一種の[[モジュール|プログラムモジュール]]機能として定義されており、その実装は[[Simula|Simula67]]由来の[[継承 (プログラミング)|継承]]と動的ディスパッチを加えた[[抽象データ型]]のスーパーセットにされていることが多い。クラスのデータ構造は[[レコード型]]や[[構造体]]に似た書式で定義されることが多く、データ構造の要素は言語ごとに[[フィールド (計算機科学)|フィールド]]、[[プロパティ (プログラミング)|プロパティ]]、[[属性]]、メンバ変数などと呼ばれている。クラスに定義される操作・振る舞いは[[メソッド (計算機科学)|メソッド]]やメンバ[[関数 (プログラミング)|関数]]などと呼ばれる。メソッドとは、特定の対象に所属させることを前提にして[[This (プログラミング)|This参照]]を多相シンボルにしたディスパッチコードとしての[[関数 (プログラミング)|関数]]/[[手続き]]を意味している。
 
OOP言語の[[クラス (コンピュータ)|クラス]]と、そうでない言語での[[モジュール]]の違いを知ることは、OOPを理解する上でも重要になる。どちらも[[プロシージャ|手続き]]と[[データ]]の複合体であるが、クラスの第一の特徴はそれに[[継承 (プログラミング)|継承]]が備えられていることであり、次に[[This (プログラミング)|This参照]]の機構と、[[継承 (プログラミング)|継承]]構造上の[[内包と外延|内包]]的な{{仮リンク|動的ディスパッチ|en|Dynamic dispatch}}である。その次になる{{仮リンク|情報隠蔽|en|information hiding}}と、定義と実装に分離しての[[抽象化 (計算機科学)|抽象化]]の機構は、OOP以前の{{仮リンク|モジュラルプログラミング|en|Modular programming}}からのものである。振る舞い抽象を担っている[[インタフェース (抽象型)|インターフェース]]の概念もそちらが先例であったが、データ抽象を担っている[[カプセル化]](情報隠蔽とThis参照の融合)の採用はOOPが最初である。[[継承 (プログラミング)|継承]]構造上の内包的な動的ディスパッチによる[[派生型|サブタイピング]](=[[ポリモーフィズム]])はOOP発祥であるが、それを純粋化すると前述の[[インタフェース (抽象型)|インターフェース]]になる。OOP以前の[[構造化分析設計技法|構造化開発]]のモジュールには情報隠蔽はあるが、[[継承 (プログラミング)|継承]]はなく、[[カプセル化]]や[[ポリモーフィズム]]といった抽象化の諸機構も持たない。なお、{{仮リンク|振る舞いサブタイピング|en|Behavioral subtyping}}は[[多重ディスパッチ]]のOOPでは軽視されており、カプセル化は[[動的型付け]]のOOPではしばしば軽視されている。従ってクラスを特徴付けている要素とは即ち[[継承 (プログラミング)|継承]]であり{{疑問点|date=2021年10月}}、継承はプログラムの再利用性と保守性を高めるためのメカニズムと定義されている。
{{要説明|date=2021年10月|title=クラスは (オブジェクトの)分類 という話があるべき。}}
 
C++様式のクラスベースは[[オブジェクト (プログラミング)|オブジェクト]]を、[[型理論]]に沿った[[型システム|型]](type)と[[型付け|型付け]]{{疑問点|date=2021年10月|title=怪しい用語}}(term)に分離している。その型の一種であるユーザー定義型(user defined type)がクラスにされており、その型付け値が[[インスタンス]]になっている。ユーザー定義型とは[[構造体]]と同じものに似たデータ複合体であり{{疑問点|date=2021年10月}}、OOPでは[[手続き]](のポインタ)も構造体メンバにされている。<!-- ユーザー定義型は[[オブジェクト型]]と呼ばれることもあるが、このオブジェクト型と後節の「[[オブジェクト (プログラミング)|オブジェクト]]」の意味上の繋がりはない。←怪しいし中途半端。今の状態ならない方がマシでしょう。-->[[クラス (コンピュータ)|クラス]]はインスタンスのひな型であり、[[インスタンス]]はクラスを実体化したものである。実体化=インスタンス化とは対象クラスの全変数内容を決定し、{{疑問点範囲|[[ヒープ領域]]の基底アドレス([[This (プログラミング)|This]])を定めた上でそこにメモリ展開するという作業|date=2021年10月|title=これだと処理系による実装のような話であり、書くとしても 典型的な実装の形態 といった言い方にしないとまずい。言語のセマンティクスとしてはもっと抽象的なモデルもありうる。 ヒープとも限らないし。「メモリを確保」ならまだわかる。}}を指している。コンパイル時にその構成が確定型チェックされるユーザー定義型は[[静的型付け]]であり、実行時にもその構成を変更でき型チェックされるユーザー定義型は[[動的型付け]]である。なお、Smalltalk様式のクラスベースは[[型理論]]の[[依存型]]に似ている。依存型は型と値の境界がない型付けである。
OOP言語の[[クラス (コンピュータ)|クラス]]と、そうでない言語での[[モジュール]]の違いを知ることは、OOPを理解する上でも重要になる。どちらも[[プロシージャ|手続き]]と[[データ]]の複合体であるが、クラスの第一の特徴はそれに[[継承 (プログラミング)|継承]]が備えられていることであり、次に[[This (プログラミング)|This参照]]の機構と、[[継承 (プログラミング)|継承]]構造上の[[内包と外延|内包]]的な{{仮リンク|動的ディスパッチ|en|Dynamic dispatch}}である。その次になる{{仮リンク|情報隠蔽|en|information hiding}}と、定義と実装に分離しての[[抽象化 (計算機科学)|抽象化]]の機構は、OOP以前の{{仮リンク|モジュラルプログラミング|en|Modular programming}}からのものである。振る舞い抽象を担っている[[インタフェース (抽象型)|インターフェース]]の概念もそちらが先例であったが、データ抽象を担っている[[カプセル化]](情報隠蔽とThis参照の融合)の採用はOOPが最初である。[[継承 (プログラミング)|継承]]構造上の内包的な動的ディスパッチによる[[派生型|サブタイピング]](=[[ポリモーフィズム]])はOOP発祥であるが、それを純粋化すると前述の[[インタフェース (抽象型)|インターフェース]]になる。OOP以前の[[構造化分析設計技法|構造化開発]]のモジュールには情報隠蔽はあるが、[[継承 (プログラミング)|継承]]はなく、[[カプセル化]]や[[ポリモーフィズム]]といった抽象化の諸機構も持たない。なお、{{仮リンク|振る舞いサブタイピング|en|Behavioral subtyping}}は[[多重ディスパッチ]]のOOPでは軽視されており、カプセル化は[[動的型付け]]のOOPではしばしば軽視されている。従ってクラスを特徴付けている要素とは即ち[[継承 (プログラミング)|継承]]であり{{疑問点|date=2021年10月}}、継承はプログラムの再利用性と保守性を高めるためのメカニズムと定義されている。
 
C++様式のクラスベースは[[オブジェクト (プログラミング)|オブジェクト]]を、[[型理論]]に沿った[[型システム|型]](type)と[[型付け|型付け値]]{{疑問点|date=2021年10月|title=怪しい用語}}(term)に分離している。その型の一種であるユーザー定義型(user defined type)がクラスにされており、その型付け値が[[インスタンス]]になっている。ユーザー定義型とは[[構造体]]と同じものであり{{疑問点|date=2021年10月}}、OOPでは[[手続き]](のポインタ)も構造体メンバにされている。<!-- ユーザー定義型は[[オブジェクト型]]と呼ばれることもあるが、このオブジェクト型と後節の「[[オブジェクト (プログラミング)|オブジェクト]]」の意味上の繋がりはない。←怪しいし中途半端。今の状態ならない方がマシでしょう。-->[[クラス (コンピュータ)|クラス]]はインスタンスのひな型であり、[[インスタンス]]はクラスを実体化したものである。実体化=インスタンス化とは対象クラスの全変数内容を決定し、{{疑問点範囲|[[ヒープ領域]]の基底アドレス([[This (プログラミング)|This]])を定めた上でそこにメモリ展開するという作業|date=2021年10月|title=これだと処理系による実装のような話であり、書くとしても 典型的な実装の形態 といった言い方にしないとまずい。言語のセマンティクスとしてはもっと抽象的なモデルもありうる。 ヒープとも限らないし。「メモリを確保」ならまだわかる。}}を指している。コンパイル時にその構成が確定されるユーザー定義型は[[静的型付け]]であり、実行時にもその構成を変更できるユーザー定義型は[[動的型付け]]である。なお、Smalltalk様式のクラスベースは[[型理論]]の[[依存型]]に似ている。依存型は型と値の境界がない型付けである。
 
=== オブジェクトとは ===
[[クラスベース]]言語での「[[オブジェクト (プログラミング)|オブジェクト]]」は、[[インスタンス]]を指す用語として説明されているが、このような重複語になった背景にはOOP原点の[[Smalltalk]]の設計がある。Smalltalkは、全てのプログラム要素は[[オブジェクト (プログラミング)|オブジェクト]]であり、全てのオブジェクトはクラスのインスタンス化であり、クラスもまたオブジェクトであり、オブジェクトは他のオブジェクトと相互作用(interaction)すると定義していた。そこでは[[クラス (コンピュータ)|クラス]]もまた[[メタクラス]](型)の[[インスタンス]]化(型付け値)になり、そのメタクラスもまた他のメタクラスのインスタンス化になっていたので、[[クラス (コンピュータ)|クラス]]と[[インスタンス]]は即ちオブジェクトの性質([[相対性]])を指すための言葉になっていた。これが[[C++]]様式では簡素化されて、クラスとインスタンスは[[型システム|型]]と[[型付け|型付け値]]の役割に固定され、メタクラスは[[リフレクション (情報工学)|リフレクション]]機能に固定されたので、クラスとインスタンス化の[[相互再帰]]が失われたオブジェクトは、相互作用できるインスタンスを指しているままで放置された。相互作用とは各種演算と同義であり、Smalltalkのクラスは相互作用できる型付け値でもあるのでオブジェクトであるが、C++様式のクラスはただの型なので演算対象に出来ないことからオブジェクトではなくなっている。
 
Smalltalk方言の[[Self]]を原点とする[[プロトタイプベース]]は、オブジェクトからクラスとインスタンスの[[相対性]]を無くしたスタイルである。数値・文字列・配列・関数・シンボル・[[構造体]]([[オブジェクト型]])といった[[プリミティブ型|基本的な型]]は備えられているが、これはオブジェクト種類の区別に特化されたものなので、[[型理論]]に沿ったクラスベースの[[型システム|それ]]とは厳密には異なっている。クラス性質を除去したオブジェクトは事実上のインスタンスに一元化されており、その全てが相互作用(interaction)する。オブジェクトの表現はスロット(シンボルとコンテンツのペアデータ)の[[可変長配列]]でなされており、オブジェクトの識別は専ら[[ダックタイピング]]によってなされる。クラス概念が無いのでサブクラス化とインスタンス化は成立せず、代わりにクローン(複製)によってオブジェクトの継承がなされており、クローンはインスタンス化の代替になる。複製元オブジェクトは、複製先オブジェクトのプロトタイプと呼ばれる。
93 ⟶ 74行目:
データ構造とそれを扱うためのメソッド群を情報隠蔽の概念と合わせてモジュール化(パッケージ化)するという手法が[[カプセル化]]と呼ばれる。カプセル化されたメソッドは、[[This (プログラミング)|This値]]が暗黙の先頭引数として常に渡されるように実装される。This値とはクラスのデータ構造をメモリ展開するための[[ヒープ領域]]の基底アドレスを指しており、インスタンス化時に確定されたThis値によってメソッドは専用のデータ構造にアクセスできる。専用メソッドを通してのデータ構造の閲覧と変更は、[[抽象データ型]]の考え方に沿ったデータ構造の抽象化を意味することになり、これは{{仮リンク|Data Abstraction|en|Abstraction (computer science)|label=データ抽象}}と呼ばれる。データ閲覧用メソッドはゲッター/アクセッサと呼ばれ、データ変更用メソッドはセッター/ミューテイタと呼ばれる。
 
{{仮リンク|情報隠蔽|en|information hiding}}とはそのクラスのデータ構造の各要素および各メソッドを必要に応じて内部隠蔽するという概念である。内部隠蔽されたデータ要素とメソッドはそのクラス外部からのアクセスが禁止される。[[抽象データ型]]本来の形式ではデータ構造のみが隠蔽対象になるので、これはデータ隠蔽とも呼ばれる。隠蔽指定外のデータ要素とメソッドは外部公開されて、そのクラス外部からもアクセス可能になる。外部公開の範囲を指定する機能は[[アクセスコントロール]]と呼ばれており、これが内部隠蔽の仕組みを担っている。クラスの[[レキシカルスコープ]]を基準にした段階的なアクセス許可範囲は可視性と呼ばれる。可視性は無制限・任意クラスグループ限定・派生クラスグループ限定・自クラス限定(内部隠蔽)の四段階が[[統一モデリング言語|UML]][[クラス図]]では標準にされている。
 
=== [[継承 (プログラミング)|継承]] ===
既存クラスのデータ/メソッド構成に、任意のデータ/メソッド構成を付け足して、既存構成+新規構成の新しいクラスを定義するという手法が[[継承 (プログラミング)|継承]]と呼ばれる。また、各クラスの共通構成パートを括りだして特有構成パートと分離することでオブジェクトを分類体系化し、同時にその共通構成パートの記号化によってソースコード内の重複記述を削減する機能とも解釈される。これは差分プログラミング目的の継承であり、1990年代までは多用さ実装継承(implementation inheritance)とも呼ばれた。
 
[[リスコフの置換原則|リスコフ置換原則]]と[[開放/閉鎖原則]]が取り上げられると、既存構成に抽象メソッドを置いて新規構成にその実装メソッドを置くという[[オーバーライド|メソッドオーバーライド]]を用いるための{{仮リンク|振る舞いサブタイピング|en|Behavioral subtyping}}目的の継承の方が重視されるようになり、これは界面継承(interface inheritance)とも呼ばれた。[[サブタイプ|サブタイピング]]による[[Is-a]]関係中心の継承をUML[[クラス図]]は特化(specialization)と定義している。
既存クラスはスーパークラス・親クラス・基底クラスなどと呼ばれ、新しいクラスはサブクラス・子クラス・派生クラスなどと呼ばれる。親と子は差分プログラミング重視で、基底と派生はサブタイピング重視で用いられる。継承できるクラスが一つに限られている単一継承を採用している言語と、継承できるクラスの数に制限がない多重継承を採用している言語がある。<!-- 概念的に インターフェース継承(型継承、[[is-a関係]]、下位分類)と 実装の継承 の2つの側面があるといったことを書いた方がよさそう。 記述によっては両方の継承関係が同時に生じる。 -->抽象メソッドを持つクラスは抽象クラスと呼ばれる。基底クラス側でリターン型とパラメータのみが定義されて実行コードブロックが未定義のままの抽象メソッドは、その派生クラス側の実装メソッドで[[オーバーライド]]される。オーバーライドは遅延結合による多相な[[複雑系]][[アルゴリズム]]を表現するオープン[[再帰]](open recursion)のメカニズムにもなっている。
 
既存クラスはスーパークラス・親クラス・基底クラスなどと呼ばれ、新しいクラスはサブクラス・子クラス・派生クラスなどと呼ばれる。親と子は差分プログラミング重視で、基底と派生はサブタイピング重視で用いられる。継承できるクラスが一つに限られている単一継承を採用している言語と、継承できるクラスの数に制限がない多重継承を採用している言語がある。<!-- 概念的に インターフェース継承(型継承、[[is-a関係]]、下位分類)と 実装の継承 の2つの側面があるといったことを書いた方がよさそう。 記述によっては両方の継承関係が同時に生じる。 -->抽象メソッドを持つクラスは抽象クラスと呼ばれる。基底クラス側でリターン型とパラメータのみが定義されて実行コードブロックが未定義のままの抽象メソッドは、その派生クラス側の実装メソッドで[[オーバーライド]]される。オーバーライドは遅延結合による多相な[[複雑系]][[アルゴリズム]]を表現するオープン[[再帰]](open recursion)のメカニズムにもなっている。
抽象メソッドのみで構成される純粋抽象クラスは[[インタフェース (抽象型)|インターフェース]]と呼ばれ、その継承をUML[[クラス図]]は実装(implementation)と定義している。インターフェースの実装は、サブタイピングの[[Is-a]]関係を完全順守させるメカニズムである。{{仮リンク|モジュラルプログラミング|en|Modular programming}}が先例になる実装は、[[継承 (プログラミング)|継承]]から[[派生型|派生]]への回帰と言えるものである。
 
抽象メソッドのみで構成される純粋抽象クラスは[[インタフェース (抽象型)|インターフェース]]と呼ばれ、その継承をUML[[クラス図]]は実装(implementation)と定義している。インターフェースの実装は、[[サブタイプ|サブタイピング]]の[[Is-a]]関係を完全順守させるメカニズムである。また、クラスへの機能注入を目的にして、主に具象メソッドをクラスに注入す継承させるという継承アプローチもあり、これは[[ミックスイン]](mix-in)と呼ばれる。mix-in具象メソッド集合体は[[トレイト]]の形態にされることが多い。トレイトmix-inUML[[抽象メソッドクラス図]]も持では扱われいない継承関係である。
 
=== [[ポリモーフィズム]] ===
124 ⟶ 105行目:
OOP原点の[[Smalltalk]]処理系由来の[[トレイト]]は、[[クラス (コンピュータ)|クラス]]への機能注入を目的にした[[メソッド (計算機科学)|メソッド]]の集合体であり、トレイトの多重継承を扱う作法は[[ミックスイン]]と呼ばれている。トレイトの継承はインクルードともされ、これはUML[[クラス図]]の特化と実装ではない第三の継承概念になるので標準OOP路線からは外れていた。
 
<!-- 以下、[[en:Object-oriented programming]] oldid=1047374345 の翻訳 -->== オブジェクト指向言語一覧 ==
===SOLID、GRASPのガイドライン===
 
[[SOLID]]は、プログラミングにおける五つの実践の頭文字をとった語呂合わせであり、マイケル・C・フェザーズ<ref>https://wiki.c2.com/?MichaelFeathers</ref>が考案し提唱したものである
* '''S''':[[:en:Single responsibility principle|単一責任の原則(英語版)]]
* '''O''':[[開放/閉鎖原則]]
* '''L''':[[リスコフの置換原則]]
* '''I''':[[:en:Interface segregation principle|インターフェイス分離の原則(英語版)]]
* '''D''':[[依存性逆転の原則]]
 
[[GRASP]](General Responsibility Assignment Software Patterns)は、[[:en:Craig Larman|クレーグ・ラーマン]]が提唱したもう一つガイドラインである。
<!-- 以上、[[en:Object-oriented programming]] oldid=1047374345 の翻訳 -->
 
== オブジェクト指向言語一覧 ==
ここではクラスベースの記述は省略している。
<div style="{{column-count|2}}">
245 ⟶ 213行目:
*[[契約による設計]]
*[[デザインパターン (ソフトウェア)|GOFデザインパターン]]
*[[GRASP]]
*[[SOLID]]
*[[リファクタリング (プログラミング)|リファクタリング]]
*[[依存性の注入]]