コンテンツにスキップ

英文维基 | 中文维基 | 日文维基 | 草榴社区

「クラス (コンピュータ)」の版間の差分

出典: フリー百科事典『ウィキペディア(Wikipedia)』
削除された内容 追加された内容
「概念」の連発を除去
 
(4人の利用者による、間の6版が非表示)
4行目: 4行目:
}}
}}


[[オブジェクト指向プログラミング]]における'''クラス'''({{lang-en-short|class}})<ref>英語の class は、本来「分類」「種類」といった意味を持っている。</ref>は、[[オブジェクト (プログラミング)|オブジェクト]]を生成するための設計図あるいはひな形に相当するものである。[[抽象データ型]]の一つ。クラスから生成したオブジェクトの実体のことを[[インスタンス]]という。
[[オブジェクト指向プログラミング]]における'''クラス'''({{lang-en-short|class}})<ref group="注釈">英語の class は、本来「分類」「種類」といった意味を持っている。</ref>は、[[オブジェクト (プログラミング)|オブジェクト]]を生成するための設計図あるいはひな形に相当するものである。[[抽象データ型]]の一つ。クラスから生成したオブジェクトの実体のことを[[インスタンス]]という。


クラスには、クラス自身またはクラスのインスタンスが保持する'''[[データ]]'''と、データに関連したオブジェクトの'''振る舞い'''を記述できる。プログラミング言語によっては、それぞれに{{仮リンク|アクセス修飾子|en|Access modifiers}}を指定できる。[[統一モデリング言語]] (UML) の[[クラス図]]では、データのことを「[[属性]]」、振る舞いのことを「操作」と呼ぶ。[[Java]]などでは、データのことを「[[フィールド (計算機科学)|フィールド]]」、振る舞いのことを「[[メソッド (計算機科学)|メソッド]]」と呼ぶ。[[C++]]などでは、データのことを「メンバー変数」、振る舞いのことを「メンバー関数」と呼ぶ。
クラスには、クラス自身またはクラスのインスタンスが保持する'''[[データ]]'''と、データに関連したオブジェクトの'''振る舞い'''を記述できる。プログラミング言語によっては、それぞれに{{仮リンク|アクセス修飾子|en|Access modifiers}}を指定できる。[[統一モデリング言語]] (UML) の[[クラス図]]では、データのことを「[[属性]]」、振る舞いのことを「操作」と呼ぶ。[[Java]]などでは、データのことを「[[フィールド (計算機科学)|フィールド]]」、振る舞いのことを「[[メソッド (計算機科学)|メソッド]]」と呼ぶ。[[C++]]などでは、データのことを「メンバー変数」、振る舞いのことを「メンバー関数」と呼ぶ。
11行目: 11行目:


プログラミング言語におけるクラスのサポートは、[[オーレ=ヨハン・ダール]]によって[[Simula|Simula 67]]において初めて導入された。この時点ではまだ[[オブジェクト指向]]の概念や用語は確立されていなかったが、のちにSimulaの影響を受けた[[ビャーネ・ストロヴストルップ]]の[[C++]]<ref>{{Cite web|url=http://www.stroustrup.com/hopl2.pdf|title=A History of C++: 1979−1991|author=Bjarne Stroustrup|accessdate=2019-02-02}}</ref>と、[[アラン・ケイ]]の[[Smalltalk]]によってオブジェクト指向が再定義されることになる。
プログラミング言語におけるクラスのサポートは、[[オーレ=ヨハン・ダール]]によって[[Simula|Simula 67]]において初めて導入された。この時点ではまだ[[オブジェクト指向]]の概念や用語は確立されていなかったが、のちにSimulaの影響を受けた[[ビャーネ・ストロヴストルップ]]の[[C++]]<ref>{{Cite web|url=http://www.stroustrup.com/hopl2.pdf|title=A History of C++: 1979−1991|author=Bjarne Stroustrup|accessdate=2019-02-02}}</ref>と、[[アラン・ケイ]]の[[Smalltalk]]によってオブジェクト指向が再定義されることになる。

== 概要 ==
{{独自研究|section=1|date=2019年1月}}
{{正確性|section=1|date=2019年1月}}
ダイクストラの[[構造化プログラミング]]は、プログラムの大規模開発への道を開いたが、あくまで単一スレッド(single thread)計算機を前提としたトップダウン型開発方法であった。すなわち、プログラムのすべての機能は単線の計算プロセス上で実行する必要があり、たとえ甲と乙という汎用的な単機能を提供する検証済みのプログラムがそれぞれ独立に存在していても、両機能を実現するプログラムを作成するためには、ソースコードから該当機能部分を抜き出し、単線上に乗るように連接(concatenation)した上で、一つのプログラムとして正しく動作するように修正し、さらに再度検証しなければならない。

一方で、複数スレッド(multi thread)計算機においては、主プログラムから、甲と乙のプログラムなどの従プログラムをそれぞれ並列に実行させた上で、処理内容を従プログラムに(OSの機能などを仲介して)伝言受け渡し(message passing)して代わりに処理させることで、検証済みプログラムのソースコードに手を加えることなく、低コストで開発することができる(以下、これ{{独自研究範囲|date=2019年1月|第0世代オブジェクト指向プログラミング}}と呼ぶ)<ref>ただし、随所にOSの機能を利用することになるため異なるOSへの移植性が低い上に、主プログラムと並列呼び出しする従プログラムが異なる言語で記述されている場合、複数の異なるコンパイラが必要となり、場合によっては複数の異なる言語を使用しなければならなくなってしまう。</ref>。

[[オーレ=ヨハン・ダール]]と[[アントニー・ホーア]]は、この第0世代オブジェクト指向プログラミングのような考え方の有効性を主張し<ref>[[#構造化プログラミング(1975)|構造化プログラミング(1975)]] pp.201-202</ref>、上記のような一連の操作を一つの言語の中で完結させるための機構を提案した。それがクラスの構文である。

ダールとホーアは、まず主プログラムから従プログラムを並列呼び出しする際、読み込みするにあたって新たに(new)割り当てられたメモリ領域に限定して走る計算プロセスを実例(instance;インスタンス)と名付け、さらにその実例の集まり('''class''' of instances)をそれが記述されたソースコードと同一視した。その上で、呼び出されたときだけではなく、存在し続ける従プログラムの実例のもとになる手続きを'''クラス'''(class)、その実例を(「クラスの実例」ではなく)改めてクラスの'''対象'''(object)と名付けた<ref name=sp202>[[#構造化プログラミング(1975)|構造化プログラミング(1975)]] p.202</ref>。さらに、その考えに基づいて[[Simula|Simula 67]]にクラスの構文を実装した<ref>
言語仕様にクラス構文を導入することで以下のような利益が得られる。
* 主プログラムと従プログラムに相当するものが異なる言語で記述されることがない。
* 複数スレッド計算機のOSに依存した以下の一連の操作を言語内部で統一的に処理できるようになる
** 主プログラムからのメモリ割り当て
** 並列呼び出し
* 抽象データ型として表現される場合、OSを仲介した伝言のやりとりのような形式ではなく、体裁上は具体的データ型のデータに対する処理への引数渡し、処理返しとして取り扱い可能になる
</ref>。


== クラス設計のための基本概念 ==
== クラス設計のための基本概念 ==
37行目: 19行目:
このように関連する変数や操作などをクラスの所属物として一つにまとめてしまうことを、クラスによる情報の[[カプセル化]](encapsulation)と呼ぶ。適切なカプセル化により、データ構造やアルゴリズムなどを変更したとしても、変更箇所はカプセル化されたクラス領域内だけで済み、変更箇所がクラス外の関連ソースコード全体にまで散乱・波及してしまうことを防ぐことができる。
このように関連する変数や操作などをクラスの所属物として一つにまとめてしまうことを、クラスによる情報の[[カプセル化]](encapsulation)と呼ぶ。適切なカプセル化により、データ構造やアルゴリズムなどを変更したとしても、変更箇所はカプセル化されたクラス領域内だけで済み、変更箇所がクラス外の関連ソースコード全体にまで散乱・波及してしまうことを防ぐことができる。


またアクセス修飾子 (access modifier) により、所属物に対して公開/非公開情報の区別をつけることで、クラス外部からクラス内に対して破壊的操作を加えることを防いだり、特定の機密データをクラス外部から見ることができないようにしたりするなど、外部に開放する情報に制限をつけることができる。カプセル化した上に公開/非公開情報の区別を加えることを'''情報隠蔽'''(information hiding)と呼ぶ<ref>[[#落水(1993) | 落水(1993) ]] p.82</ref><ref>多くのプログラミング言語ではフィールドやメソッドの定義とアクセス権の指定は同時になされるため、カプセル化と情報隠蔽はしばしば混同される。
またアクセス修飾子 (access modifier) により、所属物に対して公開/非公開情報の区別をつけることで、クラス外部からクラス内に対して破壊的操作を加えることを防いだり、特定の機密データをクラス外部から見ることができないようにしたりするなど、外部に開放する情報に制限をつけることができる。カプセル化した上に公開/非公開情報の区別を加えることを'''情報隠蔽'''(information hiding)と呼ぶ<ref>[[#落水(1993) | 落水(1993) ]] p.82</ref><ref group="注釈">多くのプログラミング言語ではフィールドやメソッドの定義とアクセス権の指定は同時になされるため、カプセル化と情報隠蔽はしばしば混同される。
</ref>。
</ref>。


=== 継承 ({{Lang|en|inheritance/extension/generalization)}} ===
=== 継承 ({{Lang|en|inheritance/extension/generalization)}} ===
{{main|継承 (プログラミング)}}
{{main|継承 (プログラミング)}}
'''継承'''(inheritance)または'''拡張'''(extension)とも呼ばれる。継承の目的は、単純なクラスに基づいてもっと複雑なクラスを構成することである。また、複雑なクラスはそれを定義する単純なクラスに従属するという意味で、クラスに階層をつけることができるようになる<ref>[[#構造化プログラミング(1975)|構造化プログラミング(1975)]] p.226</ref><ref>これが、ダールとホーアの論文の題名である『階層的プログラム構造』である。[[#ダール(1972)|ダール(1972)]]</ref>。継承の基になったクラスを'''親クラス'''/'''基本クラス'''/'''基底クラス'''/'''[[スーパークラス (計算機科学)|スーパークラス]]'''などといい、継承してできたクラスを'''子クラス'''/'''派生クラス'''/'''[[サブクラス (計算機科学)|サブクラス]]'''などという。派生クラスのインスタンスはまた基本クラスのインスタンスとしても扱えるようになる([[リスコフの置換原則]])。継承により、後述のポリモーフィズムを実現することができるようになる。
'''継承'''(inheritance)または'''拡張'''(extension)とも呼ばれる。既存のクラスに基づき新たなクラスを構成する。その目的は、単純なクラスに基づいてもっと複雑なクラスを構成することである。また、複雑なクラスはそれを定義する単純なクラスに従属するという意味で、クラスに階層をつけることができるようになる<ref>[[#構造化プログラミング(1975)|構造化プログラミング(1975)]] p.226</ref><ref group="注釈">これが、ダールとホーアの論文の題名である『階層的プログラム構造』である。[[#ダール(1972)|ダール(1972)]]</ref>。継承の基になったクラスを'''親クラス'''/'''基本クラス'''/'''基底クラス'''/'''[[スーパークラス (計算機科学)|スーパークラス]]'''などといい、継承してできたクラスを'''子クラス'''/'''派生クラス'''/'''[[サブクラス (計算機科学)|サブクラス]]'''などという。派生クラスのインスタンスはまた基本クラスのインスタンスとしても扱えるようになる([[リスコフの置換原則]])。継承により、後述のポリモーフィズムを実現することができるようになる。


UMLでは継承のことを'''汎化''' ({{Lang|en|generalization}}) と呼んでいる。汎化とはスーパークラスによる抽象化であり、対義語の'''特化''' ({{lang|en|specialization}}) はサブクラスによる具象化を指す。
UMLでは継承のことを'''汎化''' ({{Lang|en|generalization}}) と呼んでいる。汎化とはスーパークラスによる抽象化であり、対義語の'''特化''' ({{lang|en|specialization}}) はサブクラスによる具象化を指す。
53行目: 35行目:


複数の基本クラスを継承して一つの新しいクラスを派生させることを[[多重継承]] (multiple inheritance) と呼ぶ。多重継承により、基となった全てのクラスの所属物は合わせて一つになり、全ての動作が組み合わさった新しい一つのクラスが構成される。ただし、実装の多重継承は二つの基本クラスの同名メソッドの[[オーバーライド]]によるコンフリクトを始めとするいくつかの問題点([[菱形継承問題]]など)が指摘されている。したがって実装の継承は通例、一つのクラスに基づいてその拡張を行う単一継承を用いる。C++は多重継承を許可し、多重継承にまつわる問題の解決手段を[[仮想継承]]によって提供しているが、他の多くの言語、例えば[[Java]]、[[C Sharp|C#]]、[[D言語]]では実装の多重継承はサポートされておらず、[[インタフェース (抽象型)|インターフェイス]]の複数実装による型の多重継承のみサポートされている。ただしJava 8以降はインターフェイスのデフォルト実装により、実装の多重継承も限定的にサポートするようになった。なお、Simula 67は多重継承もインターフェイスもサポートしていなかった<ref>[http://staff.um.edu.mt/jskl1/talk.html#Wrong INTRODUCTION TO SIMULA | WHAT IS WRONG WITH SIMULA ?]</ref>。
複数の基本クラスを継承して一つの新しいクラスを派生させることを[[多重継承]] (multiple inheritance) と呼ぶ。多重継承により、基となった全てのクラスの所属物は合わせて一つになり、全ての動作が組み合わさった新しい一つのクラスが構成される。ただし、実装の多重継承は二つの基本クラスの同名メソッドの[[オーバーライド]]によるコンフリクトを始めとするいくつかの問題点([[菱形継承問題]]など)が指摘されている。したがって実装の継承は通例、一つのクラスに基づいてその拡張を行う単一継承を用いる。C++は多重継承を許可し、多重継承にまつわる問題の解決手段を[[仮想継承]]によって提供しているが、他の多くの言語、例えば[[Java]]、[[C Sharp|C#]]、[[D言語]]では実装の多重継承はサポートされておらず、[[インタフェース (抽象型)|インターフェイス]]の複数実装による型の多重継承のみサポートされている。ただしJava 8以降はインターフェイスのデフォルト実装により、実装の多重継承も限定的にサポートするようになった。なお、Simula 67は多重継承もインターフェイスもサポートしていなかった<ref>[http://staff.um.edu.mt/jskl1/talk.html#Wrong INTRODUCTION TO SIMULA | WHAT IS WRONG WITH SIMULA ?]</ref>。

C++ などの言語では、既存のクラスを継承したクラスを作ることで新たなメソッドの作成(追加)が可能となる。


=== ポリモーフィズム ({{Lang|en|polymorphism}}) ===
=== ポリモーフィズム ({{Lang|en|polymorphism}}) ===
{{main|ポリモーフィズム}}
{{main|ポリモーフィズム}}
クラスを継承する際に、スーパークラスの振る舞いをサブクラスの振る舞いで上書きする(置き換える)ことを'''[[オーバーライド]]'''という。あるサブクラスのインスタンスがオーバーライドされた振る舞いを持つ場合、インスタンスの具体的な内容(クラス)が分からなくても、インスタンスに対してその振る舞いを実行するよう指示すれば、見かけがスーパークラスと同じ(すなわちインターフェイスが同じ)でありながら、インスタンスの実際のクラスに応じて実行される振る舞い(処理内容)を変えることができる。このようにして、見かけが一緒なのに動作が変わることを'''[[ポリモーフィズム]](ポリモルフィズム)'''/'''多様性'''/'''多態性'''/'''多相性'''などという。
クラスを継承する際に、スーパークラスの振る舞いをサブクラスの振る舞いで上書きする(置き換える)ことを'''[[オーバーライド]]'''という。あるサブクラスのインスタンスがオーバーライドされた振る舞いを持つ場合、インスタンスの具体的な内容(クラス)が分からなくても、インスタンスに対してその振る舞いを実行するよう指示すれば、見かけがスーパークラスと同じ(すなわちインターフェイスが同じ)でありながら、インスタンスの実際のクラスに応じて実行される振る舞い(処理内容)を変えることができる。このようにして、見かけが一緒なのに動作が変わることを'''[[ポリモーフィズム]](ポリモルフィズム)'''/'''多様性'''/'''多態性'''/'''多相性'''などという。

== Simulaにおけるクラス ==
ダイクストラの[[構造化プログラミング]]は、プログラムの大規模開発への道を開いたが、あくまで単一スレッド(single thread)計算機を前提としたトップダウン型開発方法であった。すなわち、プログラムのすべての機能は単線の計算プロセス上で実行する必要があり、たとえ甲と乙という汎用的な単機能を提供する検証済みのプログラムがそれぞれ独立に存在していても、両機能を実現するプログラムを作成するためには、ソースコードから該当機能部分を抜き出し、単線上に乗るように連接(concatenation)した上で、一つのプログラムとして正しく動作するように修正し、さらに再度検証しなければならない。

一方で、複数スレッド(multi thread)計算機においては、主プログラムから、甲と乙のプログラムなどの従プログラムをそれぞれ並列に実行させた上で、処理内容を従プログラムに(OSの機能などを仲介して)伝言受け渡し(message passing)して代わりに処理させることで、検証済みプログラムのソースコードに手を加えることなく、低コストで開発することができる([[コルーチン]]用いたプログラミング)<ref group="注釈">ただし、随所にOSの機能を利用することになるため異なるOSへの移植性が低い上に、主プログラムと並列呼び出しする従プログラムが異なる言語で記述されている場合、複数の異なるコンパイラが必要となり、場合によっては複数の異なる言語を使用しなければならなくなってしまう。</ref>。

[[オーレ=ヨハン・ダール]]と[[アントニー・ホーア]]は、このような考え方の有効性を主張し<ref>[[#構造化プログラミング(1975)|構造化プログラミング(1975)]] pp.201-202</ref>、上記のような一連の操作を一つの言語の中で完結させるための機構を提案した。それがクラスの構文である。

ダールとホーアは、まず主プログラムから従プログラムを並列呼び出しする際、読み込みするにあたって新たに(new)割り当てられたメモリ領域に限定して走る計算プロセスを実例(instance;インスタンス)と名付け、さらにその実例の集まり('''class''' of instances)をそれが記述されたソースコードと同一視した。その上で、呼び出されたときだけではなく、存在し続ける従プログラムの実例のもとになる手続きを'''クラス'''(class)、その実例を(「クラスの実例」ではなく)改めてクラスの'''対象'''(object)と名付けた<ref name=sp202>[[#構造化プログラミング(1975)|構造化プログラミング(1975)]] p.202</ref>。さらに、その考えに基づいて[[Simula|Simula 67]]にクラスの構文を実装した<ref group="注釈">
言語仕様にクラス構文を導入することで以下のような利益が得られる。
* 主プログラムと従プログラムに相当するものが異なる言語で記述されることがない。
* 複数スレッド計算機のOSに依存した以下の一連の操作を言語内部で統一的に処理できるようになる
** 主プログラムからのメモリ割り当て
** 並列呼び出し
* 抽象データ型として表現される場合、OSを仲介した伝言のやりとりのような形式ではなく、体裁上は具体的データ型のデータに対する処理への引数渡し、処理返しとして取り扱い可能になる
</ref>。


== 脚注 ==
== 脚注 ==
{{脚注ヘルプ}}
=== 注釈 ===
{{Notelist}}
=== 出典 ===
<references />
<references />

== 参考文献 ==
* {{citation | author=オーレ=ヨハン・ダール, C.A.R. ホーア | title=階層的プログラム構造 | year=1972 | ref=ダール(1972) }}
** {{cite book |和書| title=構造化プログラミング | author=E.W.ダイクストラ | author2=C.A.R.ホーア | author3=O.-J.ダール | translator=野下浩平,川合慧,武市正人 | year=1975 | publisher=サイエンス社 | ref=構造化プログラミング(1975) }} (収録)
* {{cite book | 和書 | title=システム プログラム | author=川合 慧 | publisher=近代科学社 | series=コンピュータサイエンス大学講座 | year=1982 | ref=川合(1982) }}
* {{cite book | 和書 | title=ソフトウェア工学実践の基礎 | author=落水 浩一郎 | publisher=日科技連 | year=1993 | series=実践ソフトウェア開発工学シリーズ | ref=落水(1993) }}
* {{citation | author=Ole-Johan Dahl | title=The Birth of Object Orientation: the Simula Languages | year=2001| pdf=http://www.olejohandahl.info/old/birth-of-oo.pdf | ref=Dhal(2001) }}


== 関連項目 ==
== 関連項目 ==
70行目: 81行目:
* [[プロパティ (プログラミング)]]
* [[プロパティ (プログラミング)]]
* [[オブジェクト指向]] - [[オブジェクト指向プログラミング]]
* [[オブジェクト指向]] - [[オブジェクト指向プログラミング]]

== 参考文献 ==
* {{citation | author=オーレ=ヨハン・ダール, C.A.R. ホーア | title=階層的プログラム構造 | year=1972 | ref=ダール(1972) }}
** {{cite book |和書| title=構造化プログラミング | author=E.W.ダイクストラ | author2=C.A.R.ホーア | author3=O.-J.ダール | translator=野下浩平,川合慧,武市正人 | year=1975 | publisher=サイエンス社 | ref=構造化プログラミング(1975) }} (収録)
* {{cite book | 和書 | title=システム プログラム | author=川合 慧 | publisher=近代科学社 | series=コンピュータサイエンス大学講座 | year=1982 | ref=川合(1982) }}
* {{cite book | 和書 | title=ソフトウェア工学実践の基礎 | author=落水 浩一郎 | publisher=日科技連 | year=1993 | series=実践ソフトウェア開発工学シリーズ | ref=落水(1993) }}
* {{citation | author=Ole-Johan Dahl | title=The Birth of Object Orientation: the Simula Languages | year=2001| pdf=http://www.olejohandahl.info/old/birth-of-oo.pdf | ref=Dhal(2001) }}


{{データ型}}
{{データ型}}

2024年3月10日 (日) 10:59時点における最新版

オブジェクト指向プログラミングにおけるクラス: class[注釈 1]は、オブジェクトを生成するための設計図あるいはひな形に相当するものである。抽象データ型の一つ。クラスから生成したオブジェクトの実体のことをインスタンスという。

クラスには、クラス自身またはクラスのインスタンスが保持するデータと、データに関連したオブジェクトの振る舞いを記述できる。プログラミング言語によっては、それぞれにアクセス修飾子英語版を指定できる。統一モデリング言語 (UML) のクラス図では、データのことを「属性」、振る舞いのことを「操作」と呼ぶ。Javaなどでは、データのことを「フィールド」、振る舞いのことを「メソッド」と呼ぶ。C++などでは、データのことを「メンバー変数」、振る舞いのことを「メンバー関数」と呼ぶ。

クラスは、クラスベースオブジェクト指向プログラミングの基本である。また、オブジェクト指向プログラミングにおけるカプセル化継承ポリモーフィズムなどを、クラスベースのオブジェクト指向プログラミングにおいてはクラスを必要に応じて適宜使って実装する。一方、カプセル化・継承・ポリモーフィズムなどを、プロトタイプベースのオブジェクト指向プログラミングにおいてはクラスを使わずに実装する。

プログラミング言語におけるクラスのサポートは、オーレ=ヨハン・ダールによってSimula 67において初めて導入された。この時点ではまだオブジェクト指向の概念や用語は確立されていなかったが、のちにSimulaの影響を受けたビャーネ・ストロヴストルップC++[1]と、アラン・ケイSmalltalkによってオブジェクト指向が再定義されることになる。

クラス設計のための基本概念

[編集]

カプセル化 (encapsulation)

[編集]

一般にどんなプログラムであれ、プログラム機能を提供するためにはデータを保有するだけではなく、データに対する操作ができなければならない。単に複数のデータをまとめる手段としては、C言語構造体Pascalのレコード型といった形で従来の手続き型プログラミング言語においても提供されている。一方クラスは、データだけでなくそのデータに関連する操作もひとまとめにして管理する枠組みを提供する。

このように関連する変数や操作などをクラスの所属物として一つにまとめてしまうことを、クラスによる情報のカプセル化(encapsulation)と呼ぶ。適切なカプセル化により、データ構造やアルゴリズムなどを変更したとしても、変更箇所はカプセル化されたクラス領域内だけで済み、変更箇所がクラス外の関連ソースコード全体にまで散乱・波及してしまうことを防ぐことができる。

またアクセス修飾子 (access modifier) により、所属物に対して公開/非公開情報の区別をつけることで、クラス外部からクラス内に対して破壊的操作を加えることを防いだり、特定の機密データをクラス外部から見ることができないようにしたりするなど、外部に開放する情報に制限をつけることができる。カプセル化した上に公開/非公開情報の区別を加えることを情報隠蔽(information hiding)と呼ぶ[2][注釈 2]

継承 (inheritance/extension/generalization)

[編集]

継承(inheritance)または拡張(extension)とも呼ばれる。既存のクラスに基づき新たなクラスを構成する。その目的は、単純なクラスに基づいてもっと複雑なクラスを構成することである。また、複雑なクラスはそれを定義する単純なクラスに従属するという意味で、クラスに階層をつけることができるようになる[3][注釈 3]。継承の基になったクラスを親クラス基本クラス基底クラススーパークラスなどといい、継承してできたクラスを子クラス派生クラスサブクラスなどという。派生クラスのインスタンスはまた基本クラスのインスタンスとしても扱えるようになる(リスコフの置換原則)。継承により、後述のポリモーフィズムを実現することができるようになる。

UMLでは継承のことを汎化 (generalization) と呼んでいる。汎化とはスーパークラスによる抽象化であり、対義語の特化 (specialization) はサブクラスによる具象化を指す。

また、オブジェクト指向を効率よく使いこなすためには継承だけでなく集約 (aggregation)、委譲 (delegation) を理解する必要がある。

継承は、開放/閉鎖原則に基づき、単純な基本クラスからより複雑な派生クラスを構成する機構であり、コードの再利用と拡張を容易にする。逆に複雑なクラスの所属物のいくつかを除いて単純なクラスを構成しようとすると、コードの再利用と拡張を阻害することになる。

すなわち、最初から多数の所属物をカプセル化したり、基本クラスから継承するにしても多数の所属物を付け加えて極めて特化されたクラスを最初から作成してしまうと、途中でそれよりやや一般的なクラスが必要になっても代替させることができない。

複数の基本クラスを継承して一つの新しいクラスを派生させることを多重継承 (multiple inheritance) と呼ぶ。多重継承により、基となった全てのクラスの所属物は合わせて一つになり、全ての動作が組み合わさった新しい一つのクラスが構成される。ただし、実装の多重継承は二つの基本クラスの同名メソッドのオーバーライドによるコンフリクトを始めとするいくつかの問題点(菱形継承問題など)が指摘されている。したがって実装の継承は通例、一つのクラスに基づいてその拡張を行う単一継承を用いる。C++は多重継承を許可し、多重継承にまつわる問題の解決手段を仮想継承によって提供しているが、他の多くの言語、例えばJavaC#D言語では実装の多重継承はサポートされておらず、インターフェイスの複数実装による型の多重継承のみサポートされている。ただしJava 8以降はインターフェイスのデフォルト実装により、実装の多重継承も限定的にサポートするようになった。なお、Simula 67は多重継承もインターフェイスもサポートしていなかった[4]

C++ などの言語では、既存のクラスを継承したクラスを作ることで新たなメソッドの作成(追加)が可能となる。

ポリモーフィズム (polymorphism)

[編集]

クラスを継承する際に、スーパークラスの振る舞いをサブクラスの振る舞いで上書きする(置き換える)ことをオーバーライドという。あるサブクラスのインスタンスがオーバーライドされた振る舞いを持つ場合、インスタンスの具体的な内容(クラス)が分からなくても、インスタンスに対してその振る舞いを実行するよう指示すれば、見かけがスーパークラスと同じ(すなわちインターフェイスが同じ)でありながら、インスタンスの実際のクラスに応じて実行される振る舞い(処理内容)を変えることができる。このようにして、見かけが一緒なのに動作が変わることをポリモーフィズム(ポリモルフィズム)多様性多態性多相性などという。

Simulaにおけるクラス

[編集]

ダイクストラの構造化プログラミングは、プログラムの大規模開発への道を開いたが、あくまで単一スレッド(single thread)計算機を前提としたトップダウン型開発方法であった。すなわち、プログラムのすべての機能は単線の計算プロセス上で実行する必要があり、たとえ甲と乙という汎用的な単機能を提供する検証済みのプログラムがそれぞれ独立に存在していても、両機能を実現するプログラムを作成するためには、ソースコードから該当機能部分を抜き出し、単線上に乗るように連接(concatenation)した上で、一つのプログラムとして正しく動作するように修正し、さらに再度検証しなければならない。

一方で、複数スレッド(multi thread)計算機においては、主プログラムから、甲と乙のプログラムなどの従プログラムをそれぞれ並列に実行させた上で、処理内容を従プログラムに(OSの機能などを仲介して)伝言受け渡し(message passing)して代わりに処理させることで、検証済みプログラムのソースコードに手を加えることなく、低コストで開発することができる(コルーチンを用いたプログラミング)[注釈 4]

オーレ=ヨハン・ダールアントニー・ホーアは、このような考え方の有効性を主張し[5]、上記のような一連の操作を一つの言語の中で完結させるための機構を提案した。それがクラスの構文である。

ダールとホーアは、まず主プログラムから従プログラムを並列呼び出しする際、読み込みするにあたって新たに(new)割り当てられたメモリ領域に限定して走る計算プロセスを実例(instance;インスタンス)と名付け、さらにその実例の集まり(class of instances)をそれが記述されたソースコードと同一視した。その上で、呼び出されたときだけではなく、存在し続ける従プログラムの実例のもとになる手続きをクラス(class)、その実例を(「クラスの実例」ではなく)改めてクラスの対象(object)と名付けた[6]。さらに、その考えに基づいてSimula 67にクラスの構文を実装した[注釈 5]

脚注

[編集]

注釈

[編集]
  1. ^ 英語の class は、本来「分類」「種類」といった意味を持っている。
  2. ^ 多くのプログラミング言語ではフィールドやメソッドの定義とアクセス権の指定は同時になされるため、カプセル化と情報隠蔽はしばしば混同される。
  3. ^ これが、ダールとホーアの論文の題名である『階層的プログラム構造』である。ダール(1972)
  4. ^ ただし、随所にOSの機能を利用することになるため異なるOSへの移植性が低い上に、主プログラムと並列呼び出しする従プログラムが異なる言語で記述されている場合、複数の異なるコンパイラが必要となり、場合によっては複数の異なる言語を使用しなければならなくなってしまう。
  5. ^ 言語仕様にクラス構文を導入することで以下のような利益が得られる。
    • 主プログラムと従プログラムに相当するものが異なる言語で記述されることがない。
    • 複数スレッド計算機のOSに依存した以下の一連の操作を言語内部で統一的に処理できるようになる
      • 主プログラムからのメモリ割り当て
      • 並列呼び出し
    • 抽象データ型として表現される場合、OSを仲介した伝言のやりとりのような形式ではなく、体裁上は具体的データ型のデータに対する処理への引数渡し、処理返しとして取り扱い可能になる

出典

[編集]
  1. ^ Bjarne Stroustrup. “A History of C++: 1979−1991”. 2019年2月2日閲覧。
  2. ^ 落水(1993) p.82
  3. ^ 構造化プログラミング(1975) p.226
  4. ^ INTRODUCTION TO SIMULA | WHAT IS WRONG WITH SIMULA ?
  5. ^ 構造化プログラミング(1975) pp.201-202
  6. ^ 構造化プログラミング(1975) p.202

参考文献

[編集]
  • オーレ=ヨハン・ダール, C.A.R. ホーア (1972), 階層的プログラム構造 
    • E.W.ダイクストラ、C.A.R.ホーア、O.-J.ダール 著、野下浩平,川合慧,武市正人 訳『構造化プログラミング』サイエンス社、1975年。  (収録)
  • 川合 慧『システム プログラム』近代科学社〈コンピュータサイエンス大学講座〉、1982年。 
  • 落水 浩一郎『ソフトウェア工学実践の基礎』日科技連〈実践ソフトウェア開発工学シリーズ〉、1993年。 
  • Ole-Johan Dahl (2001), The Birth of Object Orientation: the Simula Languages 

関連項目

[編集]