人々が解決できる問題の複雑さは、物事をどこまで抽象化できるかによって決まります。
高度な数学や物理学は非常に抽象的なものです。非常に抽象的なレベルで研究されており、大きな進歩を遂げると、例えばアインシュタインの相対性理論の発見は世界に大きな影響を与えました。プログラミングについても同様です。抽象化のレベルが高くなるほど、より簡潔なコードを使用して記述することができます。
アラン・ケイはかつて、最初に成功したオブジェクト指向言語であり、Java の基礎となる言語の 1 つである Smalltalk の 5 つの基本的な特徴を要約しました。これらの特徴は、純粋なオブジェクト指向設計アプローチを表しています。
すべてはオブジェクトです。各オブジェクトには内部データ、メソッド、および一意のアドレスがあります。
プログラムはオブジェクトの集合であり、メッセージを送信することで相互に何をすべきかを伝えます
各オブジェクトには、他のオブジェクトで構成される独自のストレージがあります
すべてのオブジェクトには、それぞれのストレージがあります。タイプ
特定のタイプのすべてのオブジェクトは同じメッセージを受信できます
- あるいは、オブジェクトをより簡潔に記述することもできます:
オブジェクトには状態、動作、アイデンティティがあります
(2) 各オブジェクトには独自の機能があります
はソフトウェア設計の基本的な品質要件の 1 つであり、このクラスでは、すべてのメソッドと属性が 1 つの機能に対してまとめて作成されており、非常に便利です。使用します。しかし、私たちが毎日オブジェクトを設計するときに直面する問題の 1 つは、1 つのオブジェクトにあまりにも多くの機能を詰め込みすぎることです。
優れたオブジェクト指向設計では、各オブジェクトは 1 つのタスクを適切に実行し、それ以上のタスクを実行しようとはしません。このような設計には、低結合という別の利点もあります。各オブジェクトは独自の高度に結合した属性メソッドを持っているため、異なるタイプの複数のオブジェクトがそれぞれの機能を組み合わせることで、この低結合効果を実現します。
(3) カプセル化 - 隠された特定の実装
保護: 現在のクラスCurrent Package Descendant Class
- Default (変更なし): Current Class Current Package
- private: Current Class
(4) 再利用と結合
- コードの再利用と結合は、次の 1 つです。オブジェクト指向プログラミング言語によってもたらされる最も驚くべき利点です。
私たちは通常、組み合わせを「ある」という関係があると考えます。独自のクラスで継承関係を使用することを好む多くの初心者と比較して、実際、新しいクラスを確立するときは、より柔軟な構成を最初に検討する必要があります。この組み合わせで使うとデザインがより鮮明になります。
(5) 継承
継承が何を意味するかについては紹介しません。プロジェクトで親クラスを抽象化する方法を考えるとき、複数のサブクラスについて考え、複数のサブクラスを使用して何を見つけることができるかについて言及する価値があります。これらには共通点があり、親クラスを抽象化するのに非常に役立ちます。
継承関係により、基本クラス オブジェクトに送信できるすべてのメッセージはサブクラス オブジェクトにも送信できます。これは、事実上、サブクラスが親クラスと同じ型を持つことを意味します。親クラスを継承し、親クラスに新しいメソッドを作成せずにメソッドのみをオーバーライドする場合、それを純粋な置換と呼ぶことができます。純粋な置換の場合、この関係を表現するために - "is-a" を使用します。親クラスを継承するだけでなく、親クラスに基づいて新しいメソッドを追加するものについては、「is-like-a」を使用してこの関係を表現します。
(6) ポリモーフィズムと遅延バインディング機能
階層構造を扱うとき、オブジェクトを特定のオブジェクトとしてではなく、その親クラスとして扱うことがよくあります。たとえば、リストを渡す必要がある場合は、メソッドのパラメータに ArrayList か LinkedList かを区別する必要はありません。この多態性によりプログラムが大幅に強化されます。
しかし、これに関しては、最も単純だが説明が難しい問題があります。たとえば、上記のメソッドは、リストを渡した後に add 関数を呼び出します。このメソッドは、List に渡された関数に対してどの add 関数を呼び出すかをどのように認識するのでしょうか。 ?
この質問に対する答えは、オブジェクト指向プログラミングの最も重要なヒントでもあります: コンパイラーは、従来の意味での早期バインド関数呼び出しを生成しませんが、遅延バインディング メソッドを使用します。非オブジェクト指向コンパイラーによって生成された関数呼び出しは、いわゆる 早期バインディング を引き起こします。このバインド方法は、コンパイラーが特定の関数名を持つ呼び出しを生成し、ランタイムがこの関数呼び出しを解析することを意味します。実行されるコードの絶対アドレスが呼び出されます。この問題を解決するために、OOP は 遅延バインディング の概念を使用します。オブジェクトにメッセージを送信する場合、呼び出されるコードは実行時まで判断できません。コンパイラは、呼び出されたメソッドが存在することを確認し、パラメータの戻り値をチェックしますが、実行される正確なコードは知りません。
C++ では、キーワード virtual を使用して、メソッドに遅延バインディング属性によってもたらされる柔軟性を持たせることを明示的に宣言する必要があります。これは、デフォルトでは遅延バインディングではないことを意味します。 Java では、動的バインディングがデフォルトの動作です。
(7) 単一ルートの継承構造
Java では、すべてのクラスは最終的に単一の基本クラスを継承し、この基本クラスは Object です。 単一ルート継承構造には多くの利点があることがわかりました。単一ルート継承により、ガベージ コレクターの実装がはるかに簡単になります。すべてのオブジェクトには型情報があることが保証されているため、オブジェクトの型を決定できないことによるデッドロックは発生しません。
(8) オブジェクトの作成とライフサイクル
オブジェクトの作成とライフサイクルについて話すとき、多くの言語が思い浮かびますが、これらの言語はそれを異なる方法で処理します。 C++ は効率の制御が最も重要な問題であると考えているため、C++ はプログラマーに選択の権利を与えます。 newを自分で作成することもできますが、newで作成した領域を削除しないと有名なメモリリーク問題に陥ってしまいます。
Java では、すべてのオブジェクトがヒープ メモリ プールに動的に作成されます。 このように、必要なオブジェクトの数、オブジェクトのライフサイクル、およびオブジェクトの特定のタイプは実行時までわかりません。このような問題は、プログラムの実行中に関連するコードが実行された瞬間にのみ判断できます。そのため、ヒープ内に記憶域スペースを割り当てるには多くの時間がかかり、スタック内に記憶域スペースを作成する時間よりもはるかに長くなる可能性があります。スタック上のストレージの作成と解放には通常、1 つの命令のみが必要です。ヒープ ストレージの作成にかかる時間は、ストレージ メカニズムの設計によって異なります。(9) 例外処理
Exceptionはオブジェクトの一種です。彼はエラーの時点から「投げられた」。これらは、特定のタイプのエラーを処理するように特別に設計された、対応する例外ハンドラーによって「キャッチ」されます。例外処理は、エラーが発生したときにプログラムの通常の実行パスと並行して実行される別のパスのようなものです。これは完全に独立した実行パスであるため、コードの通常の実行を妨げません。
注目に値します: 例外処理はオブジェクト指向の機能ではありませんが、オブジェクト指向言語では例外処理はオブジェクトとして表現されることがよくあります。例外処理は、オブジェクト指向言語が登場する前から存在していました。
上記は Java オブジェクトの詳細な紹介です。その他の関連コンテンツについては、PHP 中国語 Web サイト (www.php.cn) に注目してください。