「クラスベース」の版間の差分
編集の要約なし |
|||
(同じ利用者による、間の17版が非表示) | |||
1行目: | 1行目: | ||
{{出典の明記|date=2015年12月}} |
{{出典の明記|date=2015年12月}} |
||
[[ファイル:CPT-OOP-objects and classes - attmeth.svg|境界|右|フレームなし|265x265ピクセル]] |
|||
'''クラスベース''' ({{lang-en-short|class-based}}) とは[[オブジェクト指向]]のスタイルのひとつで、まず「鋳型」あるいは「設計図」となる[[クラス (コンピュータ)|クラス]]があり、その鋳型によってオブジェクトの実体である[[インスタンス]]を生成する、というスタイルである。クラスベースの[[システム]]や[[プログラミング言語]]では、併せて[[カプセル化]]や[[継承 (プログラミング)|継承]]のメカニズムをサポートすることが多い。代表的なプログラミング言語は[[C++]]<ref>C++はマルチパラダイム言語であり、[[手続き型プログラミング]]言語の性質も持つが、ここではプロトタイプベースの対義語としての比較説明をするため、クラスベースの[[オブジェクト指向プログラミング]]言語に分類するものとする。</ref>や[[Java]]など。 |
|||
{{プログラミング・パラダイム}} |
|||
'''クラスベース''' ({{lang-en-short|''class-based''}}) は、[[オブジェクト指向プログラミング]]のサブパラダイムであり、[[クラス (コンピュータ)|クラス]]の仕組みを中心にした手法を指す。クラスベースはオブジェクト指向言語の間で最も広く採用されている主流のスタイルである。「[[C++]]」「[[Eiffel]]」「[[Object Pascal]]」「[[Java]]」「[[Delphi]]」「[[Ada|Ada 95]]」「[[OCaml]]」「[[COBOL|Object COBOL]]」「[[Visual Basic .NET]]」「[[C Sharp|C#]]」「[[Scala]]」「[[D言語|D]]」「[[Kotlin]]」「[[TypeScript]]」「[[Swift (プログラミング言語)|Swift]]」といった歴代のメジャー言語に支持されている。 |
|||
クラスベースのほか、オブジェクト指向における「同類のオブジェクトに同じような振舞いをさせるためのメカニズム」のもうひとつのスタイルとして、[[プロトタイプベース]]がある。プロトタイプベースのプログラミング言語の代表例としては[[JavaScript]]や[[Lua]]などがある。ただしJavaScriptの標準規格である[[ECMAScript]]は、バージョン6 (2015) 以降でクラス構文もサポートするようになった(実際には[[糖衣構文|シンタクティックシュガー]]的な機能であるが、そのような構文があると、「クラス構文もサポートするように」と言えばいかにもクラスベースになったように見えるのである)。 |
|||
[[クラス (コンピュータ)|'''クラス''']](''class'')は[[変数 (プログラミング)|変数]]と[[関数 (プログラミング)|関数]]をまとめたプログラム概念であり、[[カプセル化]]、[[継承 (プログラミング)|継承]]、[[多態性|ポリモーフィズム]]、[[コンストラクタ]]、[[デストラクタ]]の機能を備えていることで同様の[[モジュール]]と区別される。クラスおよびクラス間の関係は、[[統一モデリング言語|UML]]、[[デザインパターン (ソフトウェア)|デザインパターン]]、[[GRASP]]、[[SOLID|SOLID原則]]などの設計技法に基づいて定義されるのが一般的である。クラスは[[インスタンス]]のひな型であり、インスタンスはクラスを量化してメモリに展開したものである。クラスベースでの[[オブジェクト (プログラミング)|オブジェクト]](''object'')はインスタンスの別名としてか、またはクラスとインスタンスの双方を指した曖昧な意味合いで[[オブジェクト (プログラミング)|オブジェクト]]という用語が使われる。 |
|||
なおオブジェクト指向のスタイルとして、[[ビャーネ・ストロヴストルップ]]の[[C++]]流と、[[アラン・ケイ]]の[[Smalltalk]]流という分類がなされることもある。前者は由来となった[[Simula]]のクラスを強く受け継いだものであり、C++から派生した[[Java]]や[[C Sharp|C#]]などの大多数のオブジェクト指向言語にも受け継がれている。後者は[[アラン・ケイ]]の提唱した[[メッセージ (コンピュータ)|メッセージパッシング]]の概念に基づくものであり、[[Objective-C]]にも受け継がれている。 |
|||
<!--<ref>http://d.hatena.ne.jp/sumim/20040525/p1 を参照</ref>--> |
|||
== 特徴 == |
|||
<!-- 信頼性が担保されない個人のブログ記事は、単体では有効な出典になりえない。[[Wikipedia:信頼できる情報源]] --> |
|||
=== クラスとは === |
|||
クラスベースとは、その名の通り[[クラス (コンピュータ)|クラス]]を用いることを中心にした[[オブジェクト指向プログラミング]](OOP)を意味する。クラスとは端的に言うと任意の変数群と関数群をひとまとめにして一つの情報要素として定義できる機能である。それはコンパイル前の事前定義を意味する[[静的型付け]]で扱われることが多い。それと同様に変数と関数をまとめた機能に[[モジュール]]がある。非OOP言語のモジュールと、OOP言語のクラスを対比させてその違いを知ることが、クラスとは何かを知る早道にもなる。モジュールとクラスで共通するものに情報隠蔽がある。これはモジュール内の変数/関数をそれぞれ内部隠蔽するものと、外部公開するものに分ける機能を指す。内部隠蔽とはモジュール内限定アクセスにすることを意味する。外部公開された変数/関数をアクセスし合うモジュール間の連結関係を設定する機能は[[アクセスコントロール]]と呼ばれる。モジュール用のこの機能では、自身がアクセスする対象モジュールを明確に直指名するという方式になっている。それに対してクラス用では、対象クラスを漠然と所属カテゴリで指定するという方式になっている。後者の実装はパブリック/パッケージ/派生クラス群といった各種スコープの設定になる。この[[アクセスコントロール]]方式の違いは、モジュールを変数と関数の具体的構成に注目した具象体と見ているのに対して、クラスを変数と関数の[[操作的意味論|振る舞い的意味]]に注目した抽象体と見ていることの表われである。 |
|||
この'''抽象'''(''abstraction'')という考え方の有無がモジュールとクラスの分水嶺になっている。OOPの説明で犬や猫や車といった比喩話が多用されるのは、OOPそのものがプログラム要素の抽象化を前提にしたパラダイムだからである。犬や猫はしばしばひんしゅくを買うが、OOPでは変数や関数といったプログラム要素構造に焦点を当てずにその構造の[[操作的意味論|振る舞い的意味]]に焦点を当てているので、クラスの設計とはそれら振る舞い同士の繋がりを設計するのと同義になり、それを説明する上で最適なのは現実世界の例え話という結論に行き着くことになる。 |
|||
抽象化は変数、関数、クラスのいずれもが対象になる。変数の抽象化とは同クラス所属の関数を通して変数を参照/変更することを指し、その実装のために[[This (プログラミング)|this参照]]の仕組みが必要になり、またその徹底のために変数の情報隠蔽が必要になる(A)。OOPの情報隠蔽は変数が主眼なのでデータ隠蔽とも読み替えられる。関数の抽象化は中間参照を通しての呼び出しを指しこれは[[関数ポインタ]]と同義であるが、OOPでは基底抽象クラスと派生実装クラスに分けて抽象クラスに呼び出し用の中間参照を置き、実装クラスに呼び出し先の関数実体を置く。関数の中間参照は抽象関数と言い換えられる。これによって基底クラスの抽象関数をなんでもポインタにせずに、その派生クラスに置く同名実装関数のみに限定するという制約を課してまとめることができる(B)。従って関数の抽象化には、基底クラスと派生クラスを連結する構造が必要になる(C)。変数を持たずに抽象関数だけをまとめたクラスは、抽象化されたプログラムモジュールになる(D)。そのプロシージャ関数でプロセス、セッター関数でデータ変更、ゲッター関数でデータ取得を表現できるからである。この抽象モジュールは基底クラスと同義なので様々な派生クラスを実装できる(E)。 |
|||
上述の(A)と(D)は[[カプセル化]]、(C)と(E)は[[継承 (プログラミング)|継承]]、(B)と(E)は[[多態性|ポリモーフィズム]]に相当しこれらはOOPの三大原則などと呼ばれる。クラスの定義は諸説あるが、モジュールのプログラム概念にこの三原則仕様を表現する機能を加え、<code>instance.method()</code>のように書式されてその<code>method</code>内では<code>instance</code>のメンバに暗黙アクセスできる[[This (プログラミング)|this参照]]の機能を加え、コンストラクタによるインスタンス生成とデストラクタによるインスタンス破棄の機能も加えたものがクラスになる。 |
|||
=== インスタンス === |
|||
クラスはインスタンスのひな型であり、インスタンスとはクラスを量化(''quantification'')したものである。この量化を担当するのがコンストラクタである。ここでの量化とはクラス内の変数の内容を全て決定してメモリに展開することを指す。各変数内容の決定は初期化と呼ばれる。初期化の仕方は、コンストラクタに渡された引数を代入する方法、コンストラクタに渡された引数を任意に解釈/加工した値を代入する方法、ゼロやnull値を代入する方法、暗黙のデフォルト値を代入する方法、展開メモリ領域のその時の電荷状態のランダムビット列をそのまま値にしてしまう方法などに分かれる。またこれは言語によって実装が分かれるが、関数の中間参照テーブルも合わせてメモリ展開されることもある。クラスの変数および関数の中間参照テーブルをメモリに展開することを指してインスタンス生成という。 |
|||
インスタンスは[[This (プログラミング)|this参照]]の機能を備えている。これは<code>インスタンス.関数()</code>のような書式で呼び出された関数にインスタンスのアドレスが暗黙引数として渡されてこれがthis参照になり、その関数内ではインスタンスのメンバに暗黙アクセスできるという仕組みである。その関数は量化元クラスで定義されている。インスタンスは普通に[[構造体|データ構造体]]としても扱える。 |
|||
=== ソフトウェアモデリング === |
|||
[[モジュール]]によるソフトウェア構築では主に[[構造化分析設計技法]]関連が基準にされるのに対して、クラスベースのソフトウェア構築では[[統一モデリング言語|UML]]と[[ギャング・オブ・フォー (情報工学)|GOF]]を始めとする数々の[[デザインパターン (ソフトウェア)|デザインパターン]]が基準にされている。UMLは7種の構造図と7種の振る舞い図でソフトウェアをモデリングする。ただし[[クラス図]]、オブジェクト図、プロファイル図以外の構造図4種と振る舞い図全種は、どちらかと言うと汎用的なものであり、クラスベース向けという訳ではない。プロファイル図は[[メタクラス]]の設計に用いられるものである。オブジェクト図は一つのクラスの変数/関数を設計するものであり、データ抽象の仕様もここでデザインする。クラス間の関係を設計するクラス図はUMLで最も大きな存在感を占めるダイアグラムであり、真っ先に連想されるUMLの代名詞でもある。クラス図でのクラス間の連結線は汎化・実現・合成・集約・関連・依存の六種で表現される。このうち関連・依存・合成・集約はモジュール用の[[構造化分析設計技法]]にも存在する連結概念であるが、汎化・実現の方は前述の'''抽象'''(''abstraction'')の考え方を取り入れたクラス図特有の抽象連結概念である。 |
|||
[[モジュール]]にも、既存変数関数に新たな変数関数を付け足すための差分プログラミング用途の派生構造連結があるが、派生構造連結と[[クラス図]]での抽象連結の違いは、抽象関数機能と[[オーバーライド]]機能の有無で区別される。抽象関数とオーバーライドがない場合はただの差分用途の連結になる。差分用途の連結による[[継承 (プログラミング)|継承]]は必然的に[[結合度|密結合]]になると共に、メンバ要素の段階的な分散配置を招くので変数関数構成の把握が難しくなる。それに対して抽象関数と[[オーバーライド]]を主眼にした抽象連結による[[継承 (プログラミング)|継承]]は、変数関数構成はほぼそのままに実装内容だけを段階的に分散配置できるので、適切な抽象構成の設定で[[結合度|密結合]]によるデミリットを無くし、変数関数構成の把握難度もそのままにする(A)。また抽象連結は、モジュールの[[構造化分析設計技法]]では不可能だったクラス間の再帰関係と複数クラス間の相互再帰の構築も可能にしている(B)。特に(B)は重要である。[[ギャング・オブ・フォー (情報工学)|GOF]]を始めとする[[デザインパターン (ソフトウェア)|デザインパターン]]は、クラスベースならではの(A)と(B)の抽象特性を盛り込んだクラス間設計であり、従来のモジュール構造設計にはできない多様で柔軟かつ明瞭で平易なソフトウェアモデリングを可能にしたものである。 |
|||
== 来歴 == |
|||
[[クラス (コンピュータ)|クラス]]は、[[オブジェクト指向プログラミング]](OOP)という用語が誕生する以前に登場した機能であり、1967年公開の言語「[[Simula|Simula 67]]」が導入したものが初出である。クラスは1974年に提唱された[[抽象データ型]]の代表的実装形態として解釈されるようにもなっている。OOPの原点は1972年公開の言語「[[Smalltalk]]」で提唱された[[メッセージング]](''messaging'')であるが、それよりもクラスの方に技術的関心が集まったことでOOP=クラスとインスタンスという図式が世間に広まり、クラスは後付けでOOPの源流に位置付けられた。オブジェクト指向プログラミングが知名度を得るようになった1980年代を通してクラスとインスタンスの仕組みはその代名詞になった。OOPをスタイル分類するためのクラスベースという用語が生まれた背景には、[[The Art of the Metaobject Protocol|メタオブジェクトプロトコル]]を基礎にしたもう一つのスタイルが1990年代に登場したという理由がある。[[プロトタイプベース]]と名付けられたその手法と区別するために、クラスベースという用語もまた世間に認識されるようになった。 |
|||
== 脚注 == |
== 脚注 == |
||
{{Reflist}} |
{{Reflist}} |
||
== 関連項目 == |
|||
* [[Simula|Simula 67]] |
|||
*[[C++]] |
|||
*[[Eiffel]] |
|||
*[[クラス (コンピュータ)|クラス]] |
|||
* [[抽象データ型]] |
|||
* [[統一モデリング言語]] |
|||
* [[デザインパターン (ソフトウェア)|デザインパターン]] |
|||
* [[GRASP]] |
|||
* [[SOLID]] |
|||
{{プログラミング言語の関連項目}} |
{{プログラミング言語の関連項目}} |
||
{{Computer-stub}} |
|||
{{デフォルトソート:くらすへえす}} |
{{デフォルトソート:くらすへえす}} |
||
[[category:オブジェクト指向|くらすへえす]] |
[[category:オブジェクト指向|くらすへえす]] |
2021年2月24日 (水) 06:00時点における版
プログラミング・パラダイム |
---|
クラスベース (英: class-based) は、オブジェクト指向プログラミングのサブパラダイムであり、クラスの仕組みを中心にした手法を指す。クラスベースはオブジェクト指向言語の間で最も広く採用されている主流のスタイルである。「C++」「Eiffel」「Object Pascal」「Java」「Delphi」「Ada 95」「OCaml」「Object COBOL」「Visual Basic .NET」「C#」「Scala」「D」「Kotlin」「TypeScript」「Swift」といった歴代のメジャー言語に支持されている。
クラス(class)は変数と関数をまとめたプログラム概念であり、カプセル化、継承、ポリモーフィズム、コンストラクタ、デストラクタの機能を備えていることで同様のモジュールと区別される。クラスおよびクラス間の関係は、UML、デザインパターン、GRASP、SOLID原則などの設計技法に基づいて定義されるのが一般的である。クラスはインスタンスのひな型であり、インスタンスはクラスを量化してメモリに展開したものである。クラスベースでのオブジェクト(object)はインスタンスの別名としてか、またはクラスとインスタンスの双方を指した曖昧な意味合いでオブジェクトという用語が使われる。
特徴
クラスとは
クラスベースとは、その名の通りクラスを用いることを中心にしたオブジェクト指向プログラミング(OOP)を意味する。クラスとは端的に言うと任意の変数群と関数群をひとまとめにして一つの情報要素として定義できる機能である。それはコンパイル前の事前定義を意味する静的型付けで扱われることが多い。それと同様に変数と関数をまとめた機能にモジュールがある。非OOP言語のモジュールと、OOP言語のクラスを対比させてその違いを知ることが、クラスとは何かを知る早道にもなる。モジュールとクラスで共通するものに情報隠蔽がある。これはモジュール内の変数/関数をそれぞれ内部隠蔽するものと、外部公開するものに分ける機能を指す。内部隠蔽とはモジュール内限定アクセスにすることを意味する。外部公開された変数/関数をアクセスし合うモジュール間の連結関係を設定する機能はアクセスコントロールと呼ばれる。モジュール用のこの機能では、自身がアクセスする対象モジュールを明確に直指名するという方式になっている。それに対してクラス用では、対象クラスを漠然と所属カテゴリで指定するという方式になっている。後者の実装はパブリック/パッケージ/派生クラス群といった各種スコープの設定になる。このアクセスコントロール方式の違いは、モジュールを変数と関数の具体的構成に注目した具象体と見ているのに対して、クラスを変数と関数の振る舞い的意味に注目した抽象体と見ていることの表われである。
この抽象(abstraction)という考え方の有無がモジュールとクラスの分水嶺になっている。OOPの説明で犬や猫や車といった比喩話が多用されるのは、OOPそのものがプログラム要素の抽象化を前提にしたパラダイムだからである。犬や猫はしばしばひんしゅくを買うが、OOPでは変数や関数といったプログラム要素構造に焦点を当てずにその構造の振る舞い的意味に焦点を当てているので、クラスの設計とはそれら振る舞い同士の繋がりを設計するのと同義になり、それを説明する上で最適なのは現実世界の例え話という結論に行き着くことになる。
抽象化は変数、関数、クラスのいずれもが対象になる。変数の抽象化とは同クラス所属の関数を通して変数を参照/変更することを指し、その実装のためにthis参照の仕組みが必要になり、またその徹底のために変数の情報隠蔽が必要になる(A)。OOPの情報隠蔽は変数が主眼なのでデータ隠蔽とも読み替えられる。関数の抽象化は中間参照を通しての呼び出しを指しこれは関数ポインタと同義であるが、OOPでは基底抽象クラスと派生実装クラスに分けて抽象クラスに呼び出し用の中間参照を置き、実装クラスに呼び出し先の関数実体を置く。関数の中間参照は抽象関数と言い換えられる。これによって基底クラスの抽象関数をなんでもポインタにせずに、その派生クラスに置く同名実装関数のみに限定するという制約を課してまとめることができる(B)。従って関数の抽象化には、基底クラスと派生クラスを連結する構造が必要になる(C)。変数を持たずに抽象関数だけをまとめたクラスは、抽象化されたプログラムモジュールになる(D)。そのプロシージャ関数でプロセス、セッター関数でデータ変更、ゲッター関数でデータ取得を表現できるからである。この抽象モジュールは基底クラスと同義なので様々な派生クラスを実装できる(E)。
上述の(A)と(D)はカプセル化、(C)と(E)は継承、(B)と(E)はポリモーフィズムに相当しこれらはOOPの三大原則などと呼ばれる。クラスの定義は諸説あるが、モジュールのプログラム概念にこの三原則仕様を表現する機能を加え、instance.method()
のように書式されてそのmethod
内ではinstance
のメンバに暗黙アクセスできるthis参照の機能を加え、コンストラクタによるインスタンス生成とデストラクタによるインスタンス破棄の機能も加えたものがクラスになる。
インスタンス
クラスはインスタンスのひな型であり、インスタンスとはクラスを量化(quantification)したものである。この量化を担当するのがコンストラクタである。ここでの量化とはクラス内の変数の内容を全て決定してメモリに展開することを指す。各変数内容の決定は初期化と呼ばれる。初期化の仕方は、コンストラクタに渡された引数を代入する方法、コンストラクタに渡された引数を任意に解釈/加工した値を代入する方法、ゼロやnull値を代入する方法、暗黙のデフォルト値を代入する方法、展開メモリ領域のその時の電荷状態のランダムビット列をそのまま値にしてしまう方法などに分かれる。またこれは言語によって実装が分かれるが、関数の中間参照テーブルも合わせてメモリ展開されることもある。クラスの変数および関数の中間参照テーブルをメモリに展開することを指してインスタンス生成という。
インスタンスはthis参照の機能を備えている。これはインスタンス.関数()
のような書式で呼び出された関数にインスタンスのアドレスが暗黙引数として渡されてこれがthis参照になり、その関数内ではインスタンスのメンバに暗黙アクセスできるという仕組みである。その関数は量化元クラスで定義されている。インスタンスは普通にデータ構造体としても扱える。
ソフトウェアモデリング
モジュールによるソフトウェア構築では主に構造化分析設計技法関連が基準にされるのに対して、クラスベースのソフトウェア構築ではUMLとGOFを始めとする数々のデザインパターンが基準にされている。UMLは7種の構造図と7種の振る舞い図でソフトウェアをモデリングする。ただしクラス図、オブジェクト図、プロファイル図以外の構造図4種と振る舞い図全種は、どちらかと言うと汎用的なものであり、クラスベース向けという訳ではない。プロファイル図はメタクラスの設計に用いられるものである。オブジェクト図は一つのクラスの変数/関数を設計するものであり、データ抽象の仕様もここでデザインする。クラス間の関係を設計するクラス図はUMLで最も大きな存在感を占めるダイアグラムであり、真っ先に連想されるUMLの代名詞でもある。クラス図でのクラス間の連結線は汎化・実現・合成・集約・関連・依存の六種で表現される。このうち関連・依存・合成・集約はモジュール用の構造化分析設計技法にも存在する連結概念であるが、汎化・実現の方は前述の抽象(abstraction)の考え方を取り入れたクラス図特有の抽象連結概念である。
モジュールにも、既存変数関数に新たな変数関数を付け足すための差分プログラミング用途の派生構造連結があるが、派生構造連結とクラス図での抽象連結の違いは、抽象関数機能とオーバーライド機能の有無で区別される。抽象関数とオーバーライドがない場合はただの差分用途の連結になる。差分用途の連結による継承は必然的に密結合になると共に、メンバ要素の段階的な分散配置を招くので変数関数構成の把握が難しくなる。それに対して抽象関数とオーバーライドを主眼にした抽象連結による継承は、変数関数構成はほぼそのままに実装内容だけを段階的に分散配置できるので、適切な抽象構成の設定で密結合によるデミリットを無くし、変数関数構成の把握難度もそのままにする(A)。また抽象連結は、モジュールの構造化分析設計技法では不可能だったクラス間の再帰関係と複数クラス間の相互再帰の構築も可能にしている(B)。特に(B)は重要である。GOFを始めとするデザインパターンは、クラスベースならではの(A)と(B)の抽象特性を盛り込んだクラス間設計であり、従来のモジュール構造設計にはできない多様で柔軟かつ明瞭で平易なソフトウェアモデリングを可能にしたものである。
来歴
クラスは、オブジェクト指向プログラミング(OOP)という用語が誕生する以前に登場した機能であり、1967年公開の言語「Simula 67」が導入したものが初出である。クラスは1974年に提唱された抽象データ型の代表的実装形態として解釈されるようにもなっている。OOPの原点は1972年公開の言語「Smalltalk」で提唱されたメッセージング(messaging)であるが、それよりもクラスの方に技術的関心が集まったことでOOP=クラスとインスタンスという図式が世間に広まり、クラスは後付けでOOPの源流に位置付けられた。オブジェクト指向プログラミングが知名度を得るようになった1980年代を通してクラスとインスタンスの仕組みはその代名詞になった。OOPをスタイル分類するためのクラスベースという用語が生まれた背景には、メタオブジェクトプロトコルを基礎にしたもう一つのスタイルが1990年代に登場したという理由がある。プロトタイプベースと名付けられたその手法と区別するために、クラスベースという用語もまた世間に認識されるようになった。