私はプログラミングを始めたばかりで、さまざまなソースのさまざまな慣習を読んだり聞いたりすることから少し混乱しています。
オブジェクト指向プログラミングには4つまたは5つの概念がありますか?
新参者として、私はこれらが5つの概念であることを理解しています:
- 抽象化
- 継承
- カプセル化
- 多型
- モジュール性
では、どうして「厳密な」定義が見つからず、これらの概念のいくつかのアレンジがそこにあるように思えますか?
私はプログラミングを始めたばかりで、さまざまなソースのさまざまな慣習を読んだり聞いたりすることから少し混乱しています。
オブジェクト指向プログラミングには4つまたは5つの概念がありますか?
新参者として、私はこれらが5つの概念であることを理解しています:
では、どうして「厳密な」定義が見つからず、これらの概念のいくつかのアレンジがそこにあるように思えますか?
回答:
オブジェクト指向プログラミングには5つまたは4つのコンポーネントがありますか?
他の人が言ったように、「OO」は実際にはコンポーネントを持ちません。なぜなら、それはツールキットや明確に定義されたプロセスのセットではなく、問題のモデリングソリューションを考える方法だからです。
新参者として、私はこれらが5つのコンポーネントであることを理解しています。
抽象化、継承、カプセル化、多態性、モジュール性?
継承とポリモーフィズムはプログラミング言語の機能です。これらを理解することは良いことですが、それらはツールであることを忘れないでください(つまり、他のツールと同様に、特定の問題を解決するためにのみ使用し、目標や努力するものとして扱わないでください)。どちらも使用せずに「OO」コードを書くことができます(また、そうすべきです)。私が今まで見た中で最高の「OO」コードのいくつかは、継承やポリモーフィズムをほとんど使用していません。
抽象化、カプセル化、モジュール化は、コードとは関係がなく、問題の見方、その問題を理解しようとする方法、コードでソリューションを設計および構造化する方法に関するものです。
また、これらのデザインアイデアは「OO」に限定されません。おそらく今、おそらく基本レベルでそれらを理解している可能性があります。これには、教科書の完璧な定義を説明し、多少自明でない問題に適用できることが含まれます。理解のより深いテストには、非常に大きな複雑な問題と、どれだけの複雑さを処理できるかが与えられています。
別の理解のテストは、問題を分解するために使用するアプローチです。「OO」の新参者は、データモデリングの観点からOOについてよく教えられます(ほとんどの人が1990年代にOOを理解していたためです)。データにあまりにも多く、行動に十分に焦点を合わせていません。
例えば、典型的な例は、多くの場合のような実体を参照してくださいDog
、Cat
、Elephant
、Seagull
、Shark
、など、多くの場合、このような例を見て、すぐに考える「OO」の新人「ああ、私はと呼ばれる基本エンティティを必要とするAnimal
」、そして彼らも他に終わる可能性がありなどの中間エンティティMammal
とAmphibian
それぞれに異なる属性を持つニート継承階層構造で、。
その考え方はいくつかのオブジェクト指向の概念の非常に基本的な理解を示していますが、経験豊富なオブジェクト指向プログラマーはそのようなアプローチに決して至らず、その結論に飛び込むことはありません(そして実際には彼らが十分な情報を持っていないことを訴えます) OOモデリングではなく、モデリング。そして、これらの動物の行動について不自然な例は何も述べていないため(そして多くの人々は、OO の本質はすべて行動と機能にあると主張します)。
「OO」について学ぶための道は、モデリングしている問題の振る舞いについて何も知らない(または少なすぎる)場合、またはエンティティではなくエンティティに注意を集中するミスを犯した場合に、間違った抽象化の構築に時間を費やすことですその理由の一部は、長年にわたって書かれた非常に多くの書籍、コース、オンラインチュートリアルが、学習者を長い間その道筋に導いた(誤った)ためです(ただし、潮流は変化しています)。
全体的に、あなたの理解の多くは経験に帰着します。これまでに学んだこれらの概念は良い出発点です。途中で学ぶ必要のある概念がもっとあります(たとえば、 "SOLID"および "DRY"の原則)。理論が実際に非常に複雑な問題を実践するようになります。
「オブジェクト指向」という用語はアラン・ケイ博士によって造られたので、彼はそれが何を意味するかに関する権威ある情報源であり、彼はそれを次のように定義しています。
私にとってのOOPとは、メッセージング、ローカルの保持と状態プロセスの保護と隠蔽、およびすべてのものの極端な遅延バインディングのみを意味します。
それを分解しましょう:
実装上、メッセージングはレイトバインドプロシージャコールであり、プロシージャコールがレイトバインドである場合、設計時に呼び出しているものを知ることができないため、状態の具体的な表現について仮定することはできません。したがって、実際にはメッセージングについてであり、レイトバインディングはメッセージングの実装であり、カプセル化はその結果です。
彼は後に「大きなアイデアは「メッセージング」である」ことを明確にし、「オブジェクト指向」という用語は重要ではないもの(オブジェクト)そして本当に重要なこと(メッセージ)から注意をそらす:
Smalltalkはその構文やクラスライブラリではなく、クラスに関するものでもないということを皆に思い出させるために、前回のOOPSLAで苦労したことを思い出してください。私がずっと前にこのトピックの「オブジェクト」という用語を作り出したことは残念です。
大きなアイデアは「メッセージング」です。これがSmalltalk / Squeakの核心です(Xerox PARCフェーズでは決して完成しなかったものです)。日本人は、「間にある」を意味する小さな単語maを持っています。おそらく、最も近い英語の同等語は「インタースティシャル」です。優れた成長可能なシステムを作成するための鍵は、内部のプロパティや動作がどうあるべきかではなく、モジュールの通信方法を設計することです。インターネットを考えてみてください-生きるためには、(a)単一の標準を超えたさまざまな種類のアイデアと実現を許可する必要があり、(b)これらのアイデア間のさまざまな程度の安全な相互運用性を許可する必要があります。
(もちろん、今日、ほとんどの人はオブジェクトではなくクラスに焦点を合わせています。これはさらに間違っています。)
メタファーとメカニズムの両方として、メッセージングはオブジェクト指向の基本です。
誰かにメッセージを送信した場合、そのメッセージをどう扱うかわかりません。唯一のあなたが観察できる事は、その応答です。メッセージを自分で処理したかどうか(オブジェクトにメソッドがある場合)、メッセージを他の誰かに転送したか(委任/プロキシ)、理解したかどうかはわかりません。それがカプセル化のすべて、つまりオブジェクト指向のすべてです。期待どおりに応答する限り、プロキシを本物と区別することさえできません。
「メッセージング」のより「現代的な」用語は「動的メソッドディスパッチ」または「仮想メソッド呼び出し」ですが、それは比phorを失い、メカニズムに焦点を合わせます。
したがって、Alan Kayの定義を見るには2つの方法があります。それを単独で見ると、メッセージングは基本的にレイトバインドプロシージャコールであり、レイトバインディングはカプセル化を意味するため、#1と結論付けることができます。 #2は実際には冗長であり、OOはすべて遅延バインディングに関するものです。
しかし、彼は後で重要なことはメッセージングであると後で明らかにしたので、異なる角度からそれを見ることができます:メッセージングは遅刻です。さて、メッセージングが唯一の可能性であれば、#3は当然のことです。1つだけのものがあり、その事が遅延バインディングである場合、すべてのものは遅延バインディングです。また、メッセージングからカプセル化が続きます。
同様のポイントは、データ抽象化の理解、ウィリアムR.クックの再訪、および「オブジェクト」および「オブジェクト指向」の簡素化されたモダンな定義に対する彼の提案にも示されています。
操作の動的なディスパッチは、オブジェクトの本質的な特性です。これは、呼び出される操作がオブジェクト自体の動的プロパティであることを意味します。操作を静的に識別することはできません。また、実行することを除いて、一般に、特定の要求に応じて実行される操作を正確に特定する方法はありません。これは、常に動的にディスパッチされるファーストクラスの関数とまったく同じです。
Smalltalk-72では、オブジェクトすらありませんでした!解析、書き換え、および再ルーティングされたメッセージストリームのみがありました。最初に登場したのはメソッド(メッセージストリームを解析して再ルーティングする標準的な方法)で、後に登場したのはオブジェクト(プライベート状態を共有するメソッドのグループ化)です。継承はかなり後になり、クラスは継承をサポートする方法としてのみ導入されました。ケイの研究グループがすでにプロトタイプについて知っていたなら、そもそもクラスを導入したことはなかっただろう。
型とプログラミング言語の Benjamin Pierceは、オブジェクト指向の定義機能はOpen Recursionであると主張しています。
Alan Kayによると、オブジェクト指向はメッセージングに関するものです。William Cookによると、OOはすべて動的メソッドのディスパッチに関するものです(これは実際には同じことです)。Benjamin Pierceによれば、OOはすべてオープン再帰に関するものです。つまり、基本的には、自己参照が動的に解決されること(または少なくともそれを考える方法)、つまりメッセージングです。
ご覧のとおり、「OO」という用語を生み出した人はオブジェクトについてかなり形而上学的な見解を持ち、クックはかなり実用的な見解を持ち、ピアスは非常に厳密な数学的見解を持っています。しかし重要なことは、哲学者、プラグマティスト、理論家がすべて同意するということです!メッセージングはオブジェクト指向の1つの柱です。限目。
ここでは継承については言及していないことに注意してください!OOには継承は必須ではありません。一般に、ほとんどのオブジェクト指向言語には実装の再利用の方法がありますが、必ずしも継承である必要はありません。たとえば、何らかの形式の委任も可能です。実際、オーランド条約では、委任は継承の代替手段として議論されており、異なる形式の委任と継承がオブジェクト指向言語の設計空間内の異なる設計ポイントにどのようにつながるかについて説明しています。(実際、Javaのような継承をサポートする言語でさえ、人々は実際にそれを避けるように教えられており、オブジェクト指向には必要ないことを再び示しています。)
@Philippが述べているように、問題の根本は、プログラミング言語をオブジェクト指向にするものの公式な定義がないことです。確かに、これはおそらく良いことです。オブジェクト指向プログラミングをサポートする方法はたくさんあり、それぞれに長所と短所があります。どの言語がより「純粋なオブジェクト指向」であるかについての議論は、実際にはあまり達成されません。
しかし、あなたがリストした5つの属性を見ると、私の考えではモジュール性は間違いなく奇妙です。モジュール性は、実際にはプログラミング言語ではなくプログラムの属性です。言語レベルでは、属性は「モジュール化のサポート」であり、通常は「モジュール」または「パッケージ」メカニズムの形式をとります。
しかし、モジュラー性に対する私の本当の反対は、典型的なプログラミング言語Smalltalk-80がモジュールをまったくサポートしなかったという点で、OOプログラミングまたはOOプログラミング言語の鍵ではないということです。考えてみると、広く使用されている多くのOOPLでのモジュールの言語サポートは「弱い」です。
モジュールは「大規模なプログラミング」をサポートするように設計されています...コードベースが大きくなりすぎて、一人では完全に理解できません。また、コードをモジュール化するためにプログラミング言語のモジュールは必要ありません。
私は、他の4つの属性、および(たとえば)「継承」のモデルが純粋なオブジェクト指向であるかどうかについても議論していません。また、Alan KayはOOプログラミングを考案したとされていますが、必ずしもOO /およびOOPLの定義に優位性があることを意味するわけではありません。明らかに、そうではありません。彼は、ある信頼できるソースが、(実際には)大きな重量を運ぶことOO&OOPLsのための他の定義を与える他のソースがあります。