プログラミングにおいて、クラスはオブジェクトを作成するために使用される構文的な実体構造です。[ 1 ]: 1.3.3クラスの機能はプログラミング言語によって異なりますが、一般的に共通する側面は、特定のオブジェクトまたはそのクラスのすべてのオブジェクトに関連付けられている状態(変数)と動作(メソッド)です。 [ 2 ] [ 3 ]
オブジェクトの状態はクラスのインスタンスごとに異なる場合がありますが、クラスの状態はすべてのインスタンスで共有されます。オブジェクトメソッドは(オブジェクトを参照する暗黙的または明示的なパラメータを介して)オブジェクトの状態にアクセスできますが、クラスメソッドはアクセスできません。
言語が継承をサポートしている場合、クラスは、そのクラスのすべての状態と振る舞いに加えて、クラスをさらに特殊化する追加の状態と振る舞いを持つ別のクラスに基づいて定義できます。特殊化されたクラスはサブクラスであり、その基となるクラスはスーパークラスです。
JavaやC#のような純粋なオブジェクト指向プログラミング言語では、すべてのクラスが継承ツリーの一部となりObject、ルートクラスは となります。つまり、すべてのオブジェクトインスタンスは であるObjectか、暗黙的に を継承しますObject。これはトップ型と呼ばれます。
歴史
この概念は、1960年代にSimula言語によって主にオブジェクト指向プログラミングに導入され、それ以来多くのプログラミング言語で継続的に使用されています。 [ 1 ]: 1.3.3その作成は、事前ベースALGOL 68プログラミング言語で使用されていたブロックと同様の概念に基づいています。[ 1 ]: 1.3.2
属性
オブジェクトのライフサイクル
オブジェクトはクラスのインスタンスとして、インスタンス化によってクラスから構築されます。オブジェクトの状態のためにメモリが割り当てられ、初期化され、オブジェクトへの参照が使用元のコードに提供されます。オブジェクトは破棄されるまで使用可能です。破棄されると、その状態メモリは解放されます。
ほとんどのプログラミング言語では、コンストラクタとデストラクタを介してライフサイクルイベントでカスタムロジックを実装できます。
タイプ
オブジェクトは、各メンバ変数の型と各メンバ関数(メソッド)のシグネチャというインターフェースとしてデータ型を表現します。クラスはインターフェースの実装を定義し、クラスをインスタンス化すると、インターフェースを介して実装を公開するオブジェクトが生成されます。[ 4 ]型理論の観点から言えば、クラスは実装(具体的なデータ構造とサブルーチンの集合)であり、型はインターフェースです。異なる(具体的な)クラスは、(型システムに応じて)同じ(抽象的な)型のオブジェクトを生成できます。たとえば、型(インターフェース)Stackは、小さなスタックでは高速だがスケーラビリティが低いSmallStackと、スケーラビリティは高いが小さなスタックではオーバーヘッドが高いScalableStackによって実装される可能性があります。
構造

クラスには、構文的に記述されたデータフィールド(またはプロパティ、フィールド、データメンバー、属性) が含まれます。[ 1 ]これらは通常、プログラム実行時に状態変数に関連付けられるフィールドの型と名前です。これらの状態変数は、クラスまたはクラスの特定のインスタンスに属します。ほとんどの言語では、クラスによって定義された構造が、そのインスタンスが使用するメモリのレイアウトを決定します。他の実装も可能です。たとえば、Pythonのオブジェクトは連想キー値コンテナを使用します。[ 5 ]
Eiffelなどの一部のプログラミング言語は、クラス定義の一部として不変条件を指定し、型システムを通じてそれらを強制します。クラスの不変条件を強制するためには、状態のカプセル化が必要です。
行動
クラスまたはそのインスタンスの振る舞い(またはアクション[ 1 ] )は、メソッドを使用して定義されます。メソッドは、オブジェクトまたはクラスに対して操作を実行できるサブルーチンです。これらの操作は、オブジェクトの状態を変更したり、単にオブジェクトにアクセスする方法を提供したりします。[ 6 ]さまざまな種類のメソッドが存在しますが、それらのサポートは言語によって異なります。一部のタイプのメソッドはプログラマのコードによって作成および呼び出されますが、コンストラクタ、デストラクタ、変換演算子などの他の特殊なメソッドは、コンパイラによって生成されたコードによって作成および呼び出されます。言語によっては、プログラマがこれらの特殊なメソッドを定義して呼び出すことも許可される場合があります。[ 7 ] [ 8 ]
インタフェース
すべてのクラスは、構造と動作を提供することでインターフェースを実装(または実現)します。構造はデータと状態から成り、動作はメソッドの実装方法を指定するコードから成ります。[ 9 ]インターフェースの定義とインターフェースの実装には区別がありますが、多くのプログラミング言語ではクラス宣言がインターフェースの定義と実装の両方を行うため、この区別は曖昧になっています。ただし、インターフェースと実装を分離する機能を提供する言語もあります。たとえば、抽象クラスは実装を提供せずにインターフェースを定義できます。
クラス継承をサポートする言語では、クラスが派生元のクラスからインターフェースを継承することも可能です。
例えば、"が " を継承し、" がインターフェース " を実装する場合、" は " が提供する機能(定数とメソッドの宣言)も実装します。classZclassYclassYinterfaceXclassZinterfaceX
アクセス指定子をサポートする言語では、クラスのインターフェースは、メソッドと属性(暗黙的なゲッターメソッドとセッターメソッドによる)の両方を含む、クラスのパブリックメンバーの集合とみなされます。プライベートメンバーや内部データ構造は、外部コードから依存されることを想定していないため、インターフェースの一部ではありません。
オブジェクト指向プログラミング手法では、クラスのインターフェースの操作は互いに独立している必要があると規定されています。その結果、インターフェースのクライアントがインターフェースで宣言されたメソッドを使用する階層的な設計になります。インターフェースは、クライアントが特定の順序でインターフェースの操作を呼び出すことを要求しません。このアプローチの利点は、クライアントコードが、クライアントがオブジェクトにアクセスできるときはいつでもインターフェースの操作が使用可能であると想定できることです。[ 10 ]
インターフェースの例
テレビ前面のボタンは、プラスチック製の筐体の内側にある電気配線とユーザーをつなぐインターフェースです。「電源」ボタンを押すと、テレビの電源をオン/オフできます。この例では、あなたのテレビがインスタンスであり、各メソッドはボタンで表され、すべてのボタンがインターフェースを構成します(同じモデルの他のテレビも同じインターフェースを備えています)。最も一般的な形式では、インターフェースとは、関連するメソッドのグループを仕様化したもので、メソッドの実装は含まれていません。
テレビには、サイズやカラー対応の有無など、無数の属性があり、それらが組み合わさってテレビの構造を構成します。クラスは、テレビの属性(構造)とボタン(インターフェース)を含む、テレビの完全な記述を表します。
製造されたテレビの総数を取得するメソッドは、テレビクラスの静的メソッドとして定義できます。このメソッドはクラスに関連付けられていますが、クラスの各インスタンスのドメイン外にあります。すべてのテレビオブジェクトの集合から特定のインスタンスを見つける静的メソッドも、別の例です。
メンバーのアクセス
- プライベート(またはクラスプライベート)は、クラス自体へのアクセスを制限します。同じクラスに属するメソッドのみがプライベートメンバーにアクセスできます。
- protected(またはclass-protected)を使用すると、クラス自体とそのすべてのサブクラスがメンバーにアクセスできます。
- 「公開」とは、どのコードでもその名前でメンバーにアクセスできることを意味します。
多くのオブジェクト指向言語は上記のアクセス指定子をサポートしていますが、その意味論は異なる場合があります。
オブジェクト指向設計では、アクセス指定子とパブリックメソッドの実装の慎重な設計を組み合わせて、クラスの不変条件(オブジェクトの状態に対する制約)を強制します。アクセス指定子の一般的な使用例は、クラスの内部データとそのインターフェースを分離することです。内部構造はプライベートにされ、パブリックなアクセサメソッドを使用して、そのようなプライベートデータを検査または変更できます。
アクセス指定子は必ずしも可視性を制御するわけではなく、プライベートメンバであってもクライアントの外部コードから見える場合があります。一部の言語では、アクセスできないが可視なメンバをランタイム時に参照できます(たとえば、メンバ関数から返されるポインタによって)。ただし、クライアントコードからメンバの名前を参照して使用しようとすると、型チェッカーによって阻止されます。[ 12 ]
さまざまなオブジェクト指向プログラミング言語は、メンバーのアクセス可能性と可視性をさまざまな程度で強制し、言語の型システムとコンパイルポリシーに応じて、コンパイル時または実行時に強制します。たとえば、Java言語では、クラスのプライベート データにアクセスするクライアント コードはコンパイルできません。[ 13 ] C++言語では、プライベート メソッドは可視ですが、インターフェースからはアクセスできません。ただし、クラスのインターフェースを表す完全に抽象化されたクラスを明示的に宣言することで、それらを不可視にすることができます。[ 14 ]
一部の言語には、他のアクセシビリティ機能が備わっています。
- インスタンスとクラスのアクセス可能性:Rubyは、class- privateとclass-protectedの代わりに、instance-privateとinstance -protectedのアクセス指定子をサポートしています。これらは、インスタンスのクラスではなく、インスタンス自体に基づいてアクセスを制限するという点で異なります。[ 15 ]
- フレンド: C++ は、クラスのフレンド関数として明示的に宣言された関数が、プライベートまたはプロテクトとして指定されたメンバーにアクセスできるメカニズムをサポートしています。[ 16 ]
- パスベース: Java は、ファイルの論理パスであるJava パッケージ内のメンバーへのアクセスを制限することをサポートしています。ただし、保護されたメンバーにアクセスするために、フレームワーク クラスと同じパッケージ内のクラスを実装して Java フレームワークを拡張するのが一般的です。ソース ファイルはまったく異なる場所に存在し、別の.jarファイルにデプロイされる可能性がありますが、JVM の観点からは同じ論理パスにあることになります。[ 11 ]
継承
概念的には、スーパークラスはサブクラスのスーパーセットです。例えば、GraphicObjectは と のスーパークラスでありRectangle、EllipseはSquareのサブクラスですRectangle。これらはすべて集合論における部分集合関係でもあり、つまり、すべての正方形は長方形ですが、すべての長方形が正方形であるとは限りません。
よくある概念上の誤りとして、関係の一部をサブクラスと混同してしまうことが挙げられます。例えば、乗用車とトラックはどちらも乗り物の一種であり、これらを乗り物クラスのサブクラスとしてモデル化するのは適切です。しかし、車の部品をサブクラス関係としてモデル化するのは誤りです。例えば、車はエンジンと車体で構成されていますが、エンジンや車体を車のサブクラスとしてモデル化するのは適切ではありません。
オブジェクト指向モデリングでは、このような関係は通常、オブジェクトのプロパティとしてモデル化されます。この例では、Carクラスには というプロパティがありますparts。は、、 、 などpartsのインスタンスなどのオブジェクトのコレクションを保持するように型付けされます。UMLなどのオブジェクトモデリング言語には、「 の一部」やその他の種類の関係のさまざまな側面をモデル化する機能が含まれています。たとえば、オブジェクトのカーディナリティ、入力値と出力値の制約などのデータです。この情報は、開発者ツールによって、オブジェクトの基本的なデータ定義に加えて、get メソッドと set メソッドのエラーチェックなどの追加のコードを生成するために使用できます。[ 17 ]BodyEngineTires
オブジェクトクラスのシステムをモデル化および実装する際の重要な質問の 1 つは、クラスが 1 つ以上のスーパークラスを持つことができるかどうかです。実際の集合を扱う現実世界では、他の 1 つの集合と交差しない集合を見つけることはまれです。しかし、Flavors や CLOS などの一部のシステムでは、実行時に複数の親がこれを行う機能を提供していますが、オブジェクト指向コミュニティの多くの人が、そもそもオブジェクトクラスを使用する目的に反すると考える複雑さを導入します。複数のスーパークラスを扱う場合、どのクラスがメッセージの処理を担当するかを理解することは複雑になる可能性があります。この機能を不用意に使用すると、クラスが回避するように設計されたのと同じシステムの複雑さと曖昧さの一部を導入する可能性があります。[ 18 ]
SmalltalkやJavaといった現代のオブジェクト指向言語の多くは、実行時に単一継承を必要とします。これらの言語では、多重継承はモデリングには役立つかもしれませんが、実装には適していません。
しかし、セマンティックWebアプリケーションオブジェクトは複数のスーパークラスを持つ。インターネットの不安定性に対応するためには、このレベルの柔軟性が必要であり、Webオントロジー言語(OWL)などの技術標準はそれをサポートするように設計されている。
同様の問題として、クラス階層をランタイム時に変更できるかどうかという点があります。Flavors、CLOS、Smalltalkなどの言語は、メタオブジェクトプロトコルの一部としてこの機能をサポートしています。クラス自体が第一級オブジェクトであるため、適切なメッセージを送信することで、その構造を動的に変更することが可能です。JavaやC++のように、より厳密な型付けに重点を置く他の言語では、クラス階層をランタイム時に変更することはできません。セマンティックWebオブジェクトは、クラスをランタイム時に変更する機能を備えています。その根拠は、複数のスーパークラスを許可する根拠と同様で、インターネットは非常に動的で柔軟であるため、この変動性を管理するには階層の動的な変更が必要であるというものです。[ 19 ]
多くのクラスベースの言語は継承をサポートしていますが、継承はクラスの本質的な機能ではありません。オブジェクトベースの言語(例えば、クラシックVisual Basic)はクラスをサポートしていますが、継承はサポートしていません。
クラス間の関係
プログラミング言語は、さまざまなクラス間の関係機能をサポートしている場合があります。
構成
クラスは他のクラスで構成されることができ、それによって囲んでいるクラスとその埋め込まれているクラスとの間に構成関係が確立されます。クラス間の構成関係は、has-a関係とも呼ばれます。[ 20 ]例えば、クラスはCarクラスで構成され、クラスを含むことができますEngine。したがって、はCarを持ちますEngine。構成の1つの側面は包含であり、これはコンポーネントインスタンスを、それらを持つインスタンスによって囲むことです。囲んでいるオブジェクトが値によってコンポーネントインスタンスを含む場合、コンポーネントとその囲んでいるオブジェクトは同様のライフタイムを持ちます。コンポーネントが参照によって含まれている場合、それらは同様のライフタイムを持たない可能性があります。[ 21 ]例えば、Objective-C 2.0では次のようになります。
@interface Car : NSObject@property NSString * name ; @property Engine * engine @property NSArray * tires ;@終わりこのCarクラスには、 NSString (文字列オブジェクト)、Engine、およびNSArray (配列オブジェクト)のインスタンスが含まれています。
階層的
クラスは 1 つ以上の既存のクラスから派生することができ、それによって派生元のクラス (基底クラス、親クラス、または親クラス (スーパークラス) と派生クラス (子クラスまたはサブクラス) があります。派生クラスと派生元のクラスの関係は、一般的にis-a関係として知られています。 [ 22 ]例えば、クラス 'Button' はクラス 'Control' から派生できます。したがって、Buttonです。親クラスの構造的メンバーと動作的メンバーは、継承され継承したものに加えて、追加の構造的メンバー (データ フィールド) と動作的メンバー (メソッド) を定義できるため、特殊化となります。また、派生クラスは、言語が許可する場合、継承したメソッドをオーバーライド
すべての言語が多重継承をサポートしているわけではありません。たとえば、Java では、クラスが複数のインターフェースを実装できますが、継承できるのは 1 つのクラスのみです。[ 23 ]多重継承が許可されている場合、階層は有向非巡回グラフ(略して DAG) であり、そうでない場合はツリーです。階層では、クラスがノード、継承関係がリンクとなります。同じレベルのクラスは、異なるレベルのクラスよりも関連付けられる可能性が高くなります。この階層のレベルは、レイヤーまたは抽象化レベルと呼ばれます。
例(iPhone SDKからの簡略化されたObjective-C 2.0コード):
@interface UIResponder : NSObject //... @interface UIView : UIResponder //... @interface UIScrollView : UIView //... @interface UITableView : UIScrollView //...この例では、UITableViewはUIScrollViewであり、 UIViewであり、 UIResponderであり、NSObjectです。
モデリング
オブジェクト指向分析および統一モデリング言語(UML)では、2 つのクラス間の関連付けは、クラス間または対応するインスタンス間のコラボレーションを表します。関連付けには方向性があります。たとえば、2 つのクラス間の双方向の関連付けは、両方のクラスがそれらの関係を認識していることを示します。[ 24 ]関連付けには、その名前または目的に応じてラベルを付けることができます。[ 25 ]
関連ロールは、関連付けの最後に与えられ、対応するクラスの役割を記述します。たとえば、「subscriber」ロールは、クラス「Person」のインスタンスがクラス「Magazine」との「subscribes-to」関連付けに参加する方法を記述します。また、「Magazine」は同じ関連付けで「subscribed magazine」ロールを持ちます。関連ロールの多重度は、関連付けの他のクラスの各インスタンスに対応するインスタンスの数を記述します。一般的な多重度は、「0..1」、「1..1」、「1..*」、「0..*」で、「*」は任意の数のインスタンスを指定します。[ 24 ]
分類学
授業には多くの種類があり、その中には重複するものもあります。
抽象的かつ具体的
継承をサポートする言語において、抽象クラス、または抽象基底クラス(ABC)とは、直接インスタンス化できないクラスのことです。対照的に、具象クラスとは、直接インスタンス化できるクラスのことです。抽象クラスのインスタンス化は、具象サブクラスを介して間接的にのみ可能です。
抽象クラスは、明示的にそのようにラベル付けされるか、単に抽象メソッド(または仮想メソッド)を指定するかのいずれかです。抽象クラスは、一部のメソッドの実装を提供することができ、また、抽象クラスの直接または間接の子孫によって実装されるシグネチャを介して仮想メソッドを指定することもできます。抽象クラスから派生したクラスをインスタンス化する前に、その親クラスのすべての抽象メソッドが派生チェーン内のいずれかのクラスによって実装されている必要があります。[ 26 ]
ほとんどのオブジェクト指向プログラミング言語では、プログラマが抽象クラスを指定でき、それらのインスタンス化は許可されません。たとえば、Java、C#、PHPでは、予約語(キーワード)abstractが使用されます。[ 27 ] [ 28 ] C++では、抽象クラスは、その言語の適切な構文で指定された少なくとも 1 つの抽象メソッド (C++ の用語では純粋仮想関数) を持つクラスです。[ 26 ]
純粋仮想メソッドのみで構成されるクラスは、C++ では純粋抽象基底クラス(または純粋 ABC ) と呼ばれ、言語のユーザーからはインターフェースとしても知られています。 [ 14 ]他の言語、特に Java や C# では、言語のキーワードを介してインターフェースと呼ばれる抽象クラスのバリアントをサポートしています。これらの言語では多重継承は許可されていませんが、クラスは複数のインターフェースを実装できます。このようなクラスには、公開アクセス可能な抽象メソッドのみを含めることができます。[ 23 ] [ 29 ] [ 30 ]
ローカルおよびインナー
一部のプログラミング言語では、グローバルスコープ以外のスコープでクラスを宣言することができます。そのようなクラスには様々な種類があります。
内部クラスとは、別のクラス内で定義されたクラスのことです。内部クラスとその包含クラスとの関係も、別の種類のクラス関連付けとして扱うことができます。内部クラスは通常、包含クラスのインスタンスに関連付けられたり、包含クラスと一緒にインスタンス化されたりすることはありません。言語によっては、包含クラスの外部からクラスを参照できる場合とできない場合があります。関連する概念として、内部型(内部データ型またはネスト型とも呼ばれる)があり、これは内部クラスの概念を一般化したものです。C ++ は、内部クラスと内部型の両方をサポートする言語の例です(typedef宣言による)。[ 31 ] [ 32 ]
ローカルクラスとは、プロシージャまたは関数内で定義されたクラスのことです。このような構造では、クラス名への参照は、クラスが宣言されたスコープ内に限定されます。言語のセマンティックルールによっては、ローカルクラスには非ローカルクラスに比べて追加の制限がある場合があります。一般的な制限の1つは、ローカルクラスのメソッドが囲んでいる関数のローカル変数にアクセスできないようにすることです。たとえば、C++では、ローカルクラスは囲んでいる関数内で宣言された静的変数を参照できますが、関数の自動変数にはアクセスできません。[ 33 ]
メタクラス
メタクラスとは、インスタンスがクラスであるクラスのことです。[ 34 ]メタクラスは、クラスの集合の共通構造を記述し、デザインパターンを実装したり、特定の種類のクラスを記述したりできます。メタクラスは、フレームワークを記述するためによく使用されます。[ 35 ]
Python、Ruby、Smalltalkなどの一部の言語では、クラスもオブジェクトです。したがって、各クラスは、言語に組み込まれた固有のメタクラスのインスタンスです。[ 5 ] [ 36 ] [ 37 ] Common Lisp Object System (CLOS) は、これらのクラスとメタクラスを実装するためのメタオブジェクトプロトコル(MOP) を提供します。[ 38 ]
ファイナル
finalクラスはサブクラス化できません。これは基本的に抽象クラスとは正反対です。抽象クラスは使用するにはサブクラス化する必要があり、直接インスタンス化することはできません。finalクラスは暗黙的に具象クラスであり、直接インスタンス化できます。
finalJava、C++、PHP では、クラスはキーワードを使用して final として宣言されますsealed。C# では、この概念はキーワードで修飾された Java のクラスと混同してはいけません。Java のクラスはsealed、選択されたサブクラスからの継承のみを許可します。[ 39 ] [ 40 ] [ 41 ] [ 42 ] Kotlinのような言語では、すべてのクラスはデフォルトで final ですが、クラスから継承できるようにするには、代わりに とマークする必要がありますopen。[ 43 ]
例えば、Java のクラスは とマークされています。[ 44 ]Stringfinal
finalクラスは、サブクラス化可能なクラスでは利用できない最適化をコンパイラが実行できるようにする可能性がある。[ 45 ]
密封済み
「シールクラス」とは、継承を特定のクラスのリストに制限するクラスのことです。これはsealed、C# の final クラスを示すキーワードと混同してはいけません。シールクラスが継承できる許可されたクラスのリストは、permits句を使用して指定されます。[ 46 ]
public sealed class Quadrilateral extends Shape implements Renderable , Transformable , Comparable < Quadrilateral > , Measurable permits Parallelogram , Trapezoid , Kite { // ... }non-sealedは、sealed クラスを拡張するクラスまたはインターフェースが未知のクラスによって拡張できることを宣言するために使用される別のキーワードです。[ 47 ]
sealed class Parallelogram extends Quadrilateral { /* ... */ } sealed class Rectangle extends Parallelogram { /* ... */ }非シールクラスSquare はRectangleを継承します{ /* ... */ }// Square は非シールなので、どのクラスでも継承できます。class RedSquare extends Square { /* ... */ }開ける
オープンクラスは変更できます。通常、実行可能プログラムは顧客によって変更できません。開発者は一部のクラスを変更できますが、通常、標準クラスや組み込みクラスは変更できません。Ruby では、すべてのクラスがオープンです。Python では、クラスは実行時に作成でき、その後すべて変更できます。[ 48 ] Objective-C のカテゴリを使用すると、プログラマは既存のクラスを再コンパイルしたり、ソースコードにアクセスしたりすることなく、メソッドを追加できます。
ミックスイン
一部の言語ではミックスインを特別にサポートしていますが、多重継承を持つ言語では、ミックスインは単に「is-a-type-of」関係を表さないクラスです。ミックスインは通常、複数のクラスに同じメソッドを追加するために使用されます。たとえば、クラスは、共通の親を持たないクラスにインクルードされたときにUnicodeConversionMixin呼び出されるメソッドを提供する場合があります。unicodeToAscii()FileReaderWebPageScraper
部分的
この機能をサポートする言語では、部分クラスとは、単一のソースコードファイル内または複数のファイルにわたって定義を複数の部分に分割できるクラスのことです。 [ 49 ]これらの部分はコンパイル時にマージされるため、コンパイラの出力は部分クラスではない場合と同じになります。
部分クラスを導入する主な動機は、ビジュアルデザイナーなどのコードジェネレータの実装を容易にすることです。[ 49 ]そうでなければ、開発者が書いたコードの中に生成されたコードをインターリーブできるコードジェネレータを開発するのは困難または妥協を強いられます。部分クラスを使用すると、コードジェネレータは別のファイルまたはファイル内の粗粒度部分クラスを処理できるため、複雑な解析による生成コードの挿入が軽減され、コンパイラの効率が向上し、開発者のコードが破損する潜在的なリスクがなくなります。部分クラスの単純な実装では、コンパイラは部分クラスのすべての部分を「統合」するプリコンパイルのフェーズを実行できます。その後、コンパイルは通常どおり続行できます。[ 50 ]
部分クラス機能のその他の利点と効果は以下のとおりです。
- クラスのインターフェースと実装コードを独自の方法で分離することを可能にします。
- エディタ内で大規模なクラスを簡単にナビゲートできるようにします。
- アスペクト指向プログラミングと同様の方法で関心の分離を可能にするが、特別なツールは使用しない。
- 複数の開発者が単一のクラスを同時に作業できるため、後で個々のコードを1つのファイルにマージする必要がなくなります。
Smalltalkでは、クラス拡張という名称で部分クラスがかなり以前から存在していました。.NET Framework 2の登場に伴い、Microsoftは部分クラスを導入し、 C# 2.0とVisual Basic 2005の両方でサポートされるようになりました。WinRTも部分クラスをサポートしています。[ 51 ]
インスタンス化不可能
インスタンス化不可能なクラスを使用すると、プログラマーはクラスごとにフィールドとメソッドをグループ化し、それらのフィールドとメソッドはクラスのインスタンスを作成せずに実行時にアクセスできます。実際、この種のクラスではインスタンス化は禁止されています。
例えば、C# では、 とマークされたクラスはstaticインスタンス化できず、静的メンバー (フィールド、メソッド、その他) しか持つことができず、インスタンス コンストラクタを持つことができず、 ですsealed( は final です)。 [ 52 ]
名前不明
名前のないクラスまたは匿名クラスは、定義時に名前や識別子に束縛されません。[ 53 ] [ 54 ]これは、名前付き関数と名前のない関数に似ています。
interface Greeting { void sayHello (); }// Greeting インターフェースを実装する匿名クラスGreeting myGreeting = new Greeting () { @Override public void sayHello () { System . out . println ( "匿名クラスからのこんにちは!" ); } };myGreeting.sayHello ( ) ;利点
ソフトウェアをオブジェクトクラスに整理することの利点は、次の3つのカテゴリに分類されます。[ 55 ]
- 急速な発展
- メンテナンスの容易さ
- コードとデザインの再利用
オブジェクトクラスは、コードとユーザー間の意味的なギャップを縮小するため、迅速な開発を促進します。システムアナリストは、アカウント、顧客、請求書などについて、基本的に同じ語彙を使用して開発者とユーザーの両方と話すことができます。オブジェクトクラスは、ほとんどのオブジェクト指向環境に強力なデバッグおよびテストツールが付属しているため、迅速な開発を促進することがよくあります。クラスのインスタンスは実行時に検査され、システムが期待どおりに動作していることを確認できます。また、コアメモリのダンプを取得する代わりに、ほとんどのオブジェクト指向環境には解釈デバッグ機能があるため、開発者はプログラムのどこでエラーが発生したかを正確に分析し、どのメソッドがどの引数で呼び出されたかを確認できます。[ 56 ]
オブジェクトクラスは、カプセル化によって保守性を向上させます。開発者がオブジェクトの動作を変更する必要がある場合、変更をそのオブジェクトとその構成要素のみに限定できます。これにより、保守機能強化に伴う望ましくない副作用の可能性を低減できます。
ソフトウェアの再利用も、オブジェクトクラスを使用する大きな利点です。クラスは、継承とインターフェースを介して再利用を容易にします。新しい動作が必要な場合、多くの場合、新しいクラスを作成し、そのクラスがスーパークラスのデフォルトの動作とデータを継承し、それに応じて動作またはデータの特定の側面を調整することで実現できます。インターフェース(メソッドとも呼ばれます)を介した再利用は、別のオブジェクトが(新しい種類のオブジェクトを作成するのではなく)特定のオブジェクトクラスを呼び出す場合に発生します。この再利用方法により、あるプログラムが別のプログラムのコードを再利用する際にソフトウェアに発生する可能性のある多くの一般的なエラーが解消されます。[ 57 ]
実行時表現
データ型として、クラスは通常コンパイル時の構成要素とみなされます。[ 58 ]言語やライブラリは、クラスに関する実行時情報を表すプロトタイプまたはファクトリメタオブジェクト、あるいは、リフレクションプログラミング機能へのアクセスや実行時にデータ構造フォーマットを操作する機能を提供するメタデータもサポートする場合があります。多くの言語では、この種のクラスに関する実行時型情報は実行時には必要ないという理由で、クラスとは区別しています。一部の動的言語では、実行時とコンパイル時の構成要素を厳密に区別しないため、メタオブジェクトとクラスを区別しない場合があります。
例えば、Human がPerson クラスを表すメタオブジェクトである場合、Humanメタオブジェクトの機能を使用して Person クラスのインスタンスを作成できます。
クラスベースプログラミング
クラスベースプログラミング、またはより一般的にはクラス指向プログラミングは、すべてのオブジェクトがクラスによって作成され、オブジェクト間に継承がないオブジェクト指向プログラミングのスタイルです。[ 59 ] [ 60 ]
オブジェクト指向プログラミング(OOP)で最も普及し発展しているモデルは、オブジェクトベースモデルではなく、クラスベースモデルです。このモデルでは、オブジェクトは状態(データ)、動作(プロシージャまたはメソッド)、およびアイデンティティ(他のすべてのオブジェクトの中で唯一無二の存在)を組み合わせたエンティティです。オブジェクトの構造と動作はクラスによって定義されます。クラスとは、特定の型のすべてのオブジェクトの構文構造、つまり設計図です。オブジェクトはクラスに基づいて明示的に作成する必要があり、作成されたオブジェクトはそのクラスのインスタンスとみなされます。オブジェクトは構造体に似ていますが、メソッドポインタ、メンバアクセス制御、およびクラス階層内でクラスのインスタンス(つまり、クラスのオブジェクト)の位置を示す暗黙のデータメンバ(実行時継承機能に不可欠)が追加されています。
カプセル化
カプセル化は、ユーザーがクラスの不変条件を破ることを防ぎます。これは、インターフェースで公開されていない側面についてオブジェクトクラスの実装を変更しても、ユーザーコードに影響を与えないために有用です。カプセル化の定義は、セキュリティ上の問題よりも、関連情報のグループ化とパッケージ化(凝集度)に重点を置いています。
批評
クラスベース言語、より正確には型付き言語(サブクラス化がサブタイピングの唯一の方法である)は、実装とインターフェースを混同しているとして批判されてきた。これはオブジェクト指向プログラミングの本質的な原則である。批判者たちは、オブジェクトのコレクションを格納するバッグクラスを作成し、それを拡張してオブジェクトの重複を排除したセットクラスと呼ばれる新しいクラスを作成する可能性があると述べている。[ 61 ] [ 62 ] この場合、バッグクラスのオブジェクトを受け取る関数は、2 つのオブジェクトを追加するとバッグのサイズが 2 つ増えることを期待するかもしれないが、セットクラスのオブジェクトを渡した場合、2 つのオブジェクトを追加してもバッグのサイズが 2 つ増えるかどうかはわからない。この問題は、サブクラス化が、リスコフ置換原則として知られるサブタイピングの原則が成り立たない場合にもサブタイピングを意味するために生じる。バーバラ・リスコフとジャネット・ウィングは、1994 年の論文でこの原則を次のように簡潔に定式化した。
サブタイプ要件: Let オブジェクトについて証明可能な性質であるタイプの . それからオブジェクトに対して真であるべきであるタイプのどこではのサブタイプです .
したがって、通常はサブタイピングとサブクラス化を区別する必要がある。現在のほとんどのオブジェクト指向言語はサブタイピングとサブクラス化を区別しているが、設計手法によっては区別しないものもある。
また、よくある例として、子クラスから作成された人間オブジェクトは親クラスのオブジェクトにはなれません。これは、子クラスと親クラスがどちらも人間クラスを継承しているにもかかわらず、クラスベースの言語では実行時にオブジェクトのクラスの種類を変更できないためです。クラスベースの言語では、この制限はクラスの統一的なビューをユーザーに維持するために不可欠です。ユーザーは、メソッドの実装のいずれかがクラスの不変条件を破る変更を引き起こすかどうかを気にする必要はありません。このような変更は、オブジェクトを破棄してその場所に別のオブジェクトを構築することで行うことができます。オブジェクトはブラックボックスの抽象化として扱われ、オブジェクトIDを介してアクセスされるため、このような変更が行われた場合でも、ポリモーフィズムを使用して関連するインターフェースを維持できます。ただし、通常はオブジェクトを参照するオブジェクト参照の値が変更されるため、クライアントコードに影響が生じます。
例となる言語
Simulaはクラス抽象化を導入したが、クラスベース言語の代表的な例はSmalltalkである。その他には、 PHP、C++、Java、C#、Objective-Cなどがある。
プロトタイプベースプログラミング
クラスからオブジェクトを作成するのとは対照的に、一部のプログラミング環境ではプロトタイプオブジェクトをコピー(クローン)することでオブジェクトを作成する方法がサポートされています。[ 63 ]
関連項目
- ブロック(プログラミング) – 順番に実行される、区切られたソースコード文のグループ
- クラス図 – ソフトウェアシステムの静的な構造を記述する図
- クラス不変条件 – クラス内のすべてのオブジェクトに対して不変な性質
- クラス変数 – オブジェクトがすべて同じコピーを持つクラスで定義された変数
- 関数(コンピュータサイエンス) – 他のソフトウェアから呼び出し可能なプログラム命令のシーケンスリダイレクト先の簡単な説明を表示するページ
- インスタンス変数 – クラスのすべてのオブジェクトが独自のコピーを持つクラスのメンバ変数
- メタクラス – クラスの共通の振る舞いを記述するクラス
- オブジェクト(コンピュータサイエンス) – 状態、振る舞い、およびアイデンティティを持つ意味的なインスタンス
- 構文(プログラミング言語) – ソースコードの形式(意味は問わない) リダイレクト先の簡単な説明を表示するページ
- 変数(コンピュータサイエンス) – 特定の種類のデータを格納する名前付きコンテナリダイレクト先の簡単な説明を表示するページ
注記
- 1 2 3 4 5ダール、オーレ・ヨハン;ミールハウグ、ビョルン;クリステン・ナイガード(1970年)。共通ベース言語(PDF) (レポート)。ノルウェー コンピューティング センター。 2024-09-19 のオリジナルからアーカイブされました。2025 年8 月 20 日に取得。
- ↑ガンマら。 1995 年、p. 14.
- ↑ Bruce 2002、2.1オブジェクト、クラス、およびオブジェクトタイプ、 https://books.google.com/books?id=9NGWq3K1RwUC &pg= PA18。
- ↑ガンマら。 1995 年、p. 17.
- 1 2 "3. データモデル" . Python 言語リファレンス. Python ソフトウェア財団. 2012-04-26取得.
- ↑ Booch 1994、p. 86-88。
- ↑ 「クラス(I)」 . C++言語チュートリアル. cplusplus.com . 2012年4月29日取得。
- ↑ 「クラス(II)」 . C++言語チュートリアル. cplusplus.com . 2012年4月29日取得。
- ↑ブーチ 1994、p. 105。
- ↑パーソンズ、ジューン・ジャムリッチ (2015年6月22日)。『コンピュータ概念の新視点 2016年版、総合版』。マサチューセッツ州ボストン:Cengage Learning。ISBN 9781305271616OCLC 917155105
- 1 2 「クラスのメンバーへのアクセスを制御する」。Javaチュートリアル。Oracle。2012年 4 月 19 日に取得。
- ↑ "OOP08-CPP. プライベートデータへの参照を返さない" . CERT C++ セキュアコーディング標準. カーネギーメロン大学。2010年5月10日。2015年10月3日のオリジナルからアーカイブ。 2012年5月7日取得。
- ↑ Ben-Ari, Mordechai (2007-01-24). "2.2 識別子" (PDF) . Java のコンパイルエラーと実行時エラー. 2011-10-18 のオリジナルからアーカイブ(PDF) . 2012-05-07に取得.
- 1 2 Wild, Fred. "C++ インターフェース" . Dr. Dobb's . UBM Techweb . 2012-05-02に取得.
- ↑ "modules_and_classes: Visibility"。
- ↑ 「友情と継承」 . C++ 言語チュートリアル. cplusplus.com . 2012-04-26取得。
- ↑ Berfeld, Marya (2008年12月2日) 「IBM Rational Software Architectエディションおよび関連ソフトウェアにおけるUMLからJavaへの変換」IBM。2013年12月20日取得。
- ↑イーヴァル、ヤコブセン。マグナス・クリスターソン。パトリック・ヨンソン。グンナー・オーバーガード (1992)。オブジェクト指向ソフトウェアエンジニアリング。アディソン・ウェスリー ACM プレス。43–69ページ。ISBN 0-201-54435-0。
- ↑ Knublauch, Holger; Oberle, Daniel; Tetlow, Phil; Wallace, Evan (2006-03-09). "オブジェクト指向ソフトウェア開発者のためのセマンティックWeb入門" . W3C . 2008-07-30に取得.
- ↑ブーチ 1994、p. 180。
- ↑ Booch 1994、p. 128-129。
- ↑ブーチ 1994、p. 112。
- 1 2 "インターフェース" . Javaチュートリアル. Oracle . 2012年5月1日取得.
- 1 2 Bell, Donald. "UMLの基本: クラス図" . developer Works . IBM . 2012年5月2日取得.
- ↑ブーチ 1994、p. 179。
- 1 2 「ポリモーフィズム」 . C++ 言語チュートリアル. cplusplus.com . 2012-05-02取得。
- ↑ 「抽象メソッドとクラス」。Javaチュートリアル。Oracle 。 2012年5月2日取得。
- ↑ 「クラス抽象化」 . PHPマニュアル. PHPグループ. 2012年5月2日取得。
- ↑ 「インターフェイス(C# プログラミング ガイド)」。C# プログラミング ガイド。Microsoft。2013年 8 月 15 日に取得。
- ↑ 「継承(C# プログラミング ガイド)」。C# プログラミング ガイド。Microsoft。2012年 5 月 2 日に取得。
- ↑ 「ネストされたクラス(C++のみ)」。XL C/C++ V8.0 for AIX。IBM。2012年5月7日取得。
- ↑ 「ローカル型名(C++のみ)」。XL C/C++ V8.0 for AIX。IBM。2012年5月7日取得。
- ↑ 「ローカルクラス(C++のみ)」。XL C/C++ V8.0 for AIX。IBM。2012年5月7日取得。
- ↑ Booch 1994、p. 133-134。
- ↑ "13 クラスとメタクラス" . pharo.gforge.inria.fr . 2021-02-24 のオリジナルからアーカイブ済み. 2016-10-31に取得.
- ↑ 「クラス クラス」。
- ↑ブーチ 1994、p. 134。
- ↑ 「MOP: 概念」。Common Lisp Object System MetaObject Protocol。Association of Lisp Users。2010年11月15日のオリジナルからアーカイブ。 2012年5月8日取得。
- ↑ "sealed (C# リファレンス)" . C# リファレンス. Microsoft . 2012-05-08取得.
- ↑ 「finalクラスとメソッドの記述」。Javaチュートリアル。Oracle 。 2012年5月8日取得。
- ↑ 「PHP: final キーワード」 . PHP マニュアル. PHP グループ. 2014 年 8 月 21 日取得。
- ↑ 「シールクラス」。Oracleヘルプセンター。 2025年7月7日取得。
- ↑スタッフ (2025年12月15日) 。「継承」。Kotlinlang.org。JetBrains sro
- ↑ "String (Java Platform SE 7)" . Java Platform, Standard Edition 7: API Specification . Oracle . 2012-05-08取得.
- ↑ Brand, Sy (2020年3月2日). 「Finalクラスのパフォーマンス上の利点」 . Microsoft C++チームブログ. Microsoft . 2020年4月4日取得。
- ↑ 「シールクラス」。docs.oracle.com。Oracleヘルプセンター。 2025年10月16日取得。
- ↑ Oracle Corporation. "4 - シールドクラス" . docs.oracle.com . Oracle Corporation . 2026年6月7日取得.
- ↑ "9. クラス" . Python チュートリアル. Python.org . 2018 年3 月 3 日取得.
モジュールと同様に、クラスも Python の動的な性質を担っています。つまり、実行時に作成され、作成後もさらに変更できます。
- 1 2 mairaw; BillWagner; tompratt-AQ (2015-09-19)、「部分クラスとメソッド」、C# プログラミング ガイド、Microsoft 、2018-08-08取得
- ↑ 「部分クラスと部分メンバー - C#」。
- ↑ BillWagner (2024-11-14). "部分クラスとメソッド - C#" . learn.microsoft.com . 2025-02-06に取得.
- ↑ 「静的クラスと静的クラスメンバー(C# プログラミング ガイド)」。C# プログラミング ガイド。Microsoft。2012年 5 月 8 日に取得。
- ↑ 「匿名クラス(Javaチュートリアル > Java言語の学習 > クラスとオブジェクト)」。docs.oracle.com 。 2021年5月13日取得。
- ↑ 「PHP: 匿名クラス - マニュアル」 . www.php.net . 2021年8月11日取得。
- ↑ 「オブジェクトとは何か?」。oracle.com。Oracle Corporation 。 2013年12月13日取得。
- ↑ブーチ、グラディ;ロバート A. マクシムチュク;マイケル W. エングル;ボビー J. ヤング博士;ジム コナレン;ケリー A. ヒューストン(2007 年 4 月 30 日)。オブジェクト指向分析と設計とその応用。アディソン・ウェスリー・プロフェッショナル。pp. 1–28。ISBN 978-0-201-89551-32013年12月20日取得。
人間の認知には根本的な制限要因があり、分解、抽象化、階層化を用いることでこれらの制約に対処できます。
- ↑イーヴァル、ヤコブセン。マグナス・クリスターソン。パトリック・ヨンソン。グンナー・オーバーガード (1992)。オブジェクト指向ソフトウェアエンジニアリング。アディソン・ウェスリー ACM プレス。ISBN 0-201-54435-0。
- ↑ 「C++ 国際標準」(PDF)。作業草案、プログラミング言語 C++ の標準。ISO/IEC JTC1/SC22 WG21。2017年12月9日のオリジナルからアーカイブ(PDF) 。 2020年1月5日取得。
- ↑ Wegner, Peter (1987). "オブジェクト指向言語設計の次元" .オブジェクト指向プログラミングシステム、言語、アプリケーションに関する会議議事録. pp. 168–182 . doi : 10.1145/38765.38823 . ISBN 0-89791-247-0。
- ↑ Liskov, Barbara (1996). "CLUの歴史" .プログラミング言語の歴史---II . pp. 471–510 . doi : 10.1145/234286.1057826 . ISBN 0-201-89502-1。
- ↑ Kiselyov, Oleg. "サブタイピング、サブクラス化、およびOOPの問題点" . 2012年10月7日取得。
- ↑デュカス、ステファン。「集合は袋のサブタイプにはなり得ない」 。 2012年10月7日取得。
- ↑ Amir, Masroor (2023年3月25日). "OOP - オブジェクト指向プログラミング - 概念 | 言語 | 利点[ 2023 ] " . The Geeks Bot: ギークのためのコンピュータサイエンスサイト. 2023年4月4日取得.
参考文献
さらに読む
- 授業(コンピュータプログラミング)
- プログラミング構成要素
- プログラミング言語のトピック
