ソフトウェアの複雑さを管理するためにオブジェクト指向言語が本当に必要ですか?


209

これは非常に非技術的でソフトな質問になりますが、これが適切なプラットフォームかどうかはわかりません。しかし、私はCSの始まりの学生なので、皆さんがそれを許容することを願っています。

最初の学期では、JavaやUMLを介して、カプセル化、データ隠蔽、モジュール性、継承などのOOPの概念を紹介しました。(Javaは私の最初のプログラミング言語です)

私の理解では、OOPはソフトウェアの複雑さを管理する方法です。しかし、その原則は新しいものやユニークなものではなく、ある意味ではすべてのエンジニアリング分野に共通しています。

たとえば、車は非常に複雑な構造であり、その複雑さは、明確に定義された動作とインターフェイスを備えたモジュール化されカプセル化されたコンポーネントの階層によって管理されます。

しかし、新しいプログラミングパラダイムを導入した理由はわかりません。複雑さを管理するために使用されるすべての原則は、手続き型プログラミング言語によって実現できると思います。たとえば、モジュール性のために、プログラムを、コードが別々のファイルに含まれる明確に定義されたタスクを実行する多くの小さなプログラムに分割することができます。これらのプログラムは、明確に定義された入力と出力を介して互いに対話します。カプセル化を実現するために、ファイルを保護(暗号化?)することができます。コードを再利用するために、新しいプログラムで必要になったときにいつでもこれらのファイルを呼び出すことができます。これは、OOPが何であるかをすべてキャプチャしないのですか、それとも非常に明白な何かを見逃していますか?

OOPが複雑さを管理しているという証拠を求めていません。私の意見では確かにそうです。しかし、モジュール性、カプセル化、データ隠蔽などの複雑さを管理するために使用されるすべての原則は、手続き型言語によって非常に簡単に実装できると思います。それでは、複雑さを管理せずに管理できるのに、なぜ本当にOOPなのでしょうか?


41
インターフェイスと実装の分離が欠落しています。実行時にある実装を別の実装に交換できることは、非常に重要な機能です。基本的に、これは、継承を伴うOO言語の動的メソッドディスパッチによって実現されます。手続き型言語でも同様のことができます(読み取り:voidポインター)が、タイプセーフはありません。
marstato

81
大部分において、オブジェクト指向言語とデザインの考え方は、これらの普遍的で直感的な概念をできるだけ簡単にコードで表現および再作成できるようにすることです。本質的にオブジェクト指向言語を使用せずにこれらすべてを実現するためのスキームまたは一連のガイドラインがある場合、物事の実行方法に関する提案は、効果的に使用されるオブジェクト指向方法論になります。実際のオブジェクト指向言語は、それを形式化および単純化するための単なる方法です。
スタンドバック

14
@RobbieDee実際に私の質問を読んでくれましたか?それは、OOなしでソフトウェアの複雑さを管理できる天気に疑問を投げかけることによって、より基本的なレベルでOOを理解しようとすることです。私はオブジェクト指向を弱体化させようとはせず、何か新しいものを発明しようとはせず、それをよりよく理解しようとしています。それが質問がとても「自明」であれば、なぜそれがヨルグから優れた答えを受け取ったのですか?
ステーキ交換

12
ファイルの暗号化はカプセル化ではありません。別の開発者からのコードの内容を見ることを不明瞭にしたかもしれませんが、必ずしも他のコードからコードの内部動作を保護しているわけではありません。元の作者は、暗号化の前後にこれを行うことができます。
JeffO

8
機械語以外に何も必要ありません。プログラマーにオペコードを記憶させ、自分でオペコードとゼロを書きましょう。しかし、ある種の「シンボリック」言語を持つことは、エラーを減らし、生産性を高めるという点で非常に有用です。また、ダイクストラが観察したように、「構造」を課す(または少なくとも「構造」の維持を容易にする)言語はかなり役立ちます。OO言語は、現在のレベルの言語の洗練度を考えると、理想的なテクノロジーではないかもしれませんが、多くのアプリケーションにはかなり適しています。アイデアは、邪魔にならずに複雑さを管理することです。
ダニエルRヒックス

回答:


177

私は本当に低い理論の答えで試してみましょう:)

あなたが本当に求めているのは、オブジェクト指向(OO)のサポートを言語に直接含めるのは、手続き型言語を使用してOOコードを設計および記述することができるのはなぜですか?

そして、答えは次のとおりです。オブジェクトコードがソースコードでどのように表現されるかについての標準を持ち、同じ抽象化に対して22の異なる実装にならないようにします。

たとえば、ユーザーインターフェイスシステムで使用できるとを作成するMagicButtonとしましょうMagicSlider。MagicButtonで使用できるメソッド、MagicSliderでのみ使用できるメソッド、および両方で使用できるメソッドをグループ化する方法が必要です。これらのオブジェクトは両方ともMagic guiオブジェクトであるため、いくつかのメソッドを共有します。

特別な方法MagicSlider_DoSomething ...で名前を付けた特定のファイルにメソッドを含めることで、特別な方法で関数に名前を付けることでグループ化を行うMagicSliderMethods.XXXことができます。または、同じことを行う他の特別な方法を見つけることができます。それを行うための標準的な方法が言語にない場合、私はあなたとは異なる方法で、そして他の誰かとは異なる方法でそれを行います。これにより、コードの共有がはるかに困難になります。

はい、遅延ディスパッチ(オブジェクト指向言語の仮想メソッド)は手続き型言語で実装できますが、実装にはさまざまな方法があります。誰がコードを書いたかに応じて、同じプログラム内で異なるOOの実装になります。

貧弱なメンテナンス開発者について考えてください。この人は、元のコードを書いた人に応じて、異なるオブジェクトの抽象化と仮想メソッドを呼び出す異なる方法を管理する必要があります。

また、言語を抽象化することで、Eclipseなどの高度なコードエディターがコードに対して多くの静的分析を実行できるようになります。たとえば、Eclipseは、オブジェクトで使用できるすべてのメソッドのリストと、空の「TODOメソッド」の自動実装を提供できます。Eclispeは、拡張するクラスと実装するインターフェイスに基づいて、クラスが実装する必要のあるメソッドを正確に把握しています。オブジェクト指向を行うための言語標準がなければ、これはほとんど不可能です。


40
古典的な例:Lua。それはネイティブにオブジェクト指向ではありませんが、作成することはできますが、これは完全に相互運用可能ではない約5つの異なる同様に有名なオブジェクト指向ライブラリがあることを意味します。
クロルタン

55
@steakexchange絶対に集中しすぎる。「唯一の目的」を持つものはほとんどありません。すべての言語は、品質の程度が異なる多くの異なることを行います。言語を選択することは、あなたがそれを必要とする目的に最も合うようにするトレードオフのセットを選択することです。
ティムB

42
@nocomprende抽象化の標準化は、ほぼ文字通りプログラミング言語の目的です。アセンブリ言語でさえ、10年半にわたって10世代のハードウェア世代の違いを抽象化します。
デビッドモールズ

56
@DavidMoles標準化された抽象化は、 文字通りプログラミング言語です。文字通り「文字通り」使用する絶好の機会を無駄にしないでください!
クレメントチャーリン

12
これを標準化することは可能です。私が90年代半ばに大学に戻ったとき、私はX-Windowsでかなりの量の仕事をしました(そのようなことを覚えている人のために、主にMotifに基づいています)。X-Windowsでは、実際に、通常のCでオブジェクト指向のすべての機能を実装できました。しかし、そうするための精神的な体操はかなり実質的であり、箱の中を見ていない人々に大きく依存していました(その時点で、シュレーディンガーのウィジェットコードは一般に死んでしまいました)。OO言語は、通常のコンパイラーがアセンブラーに対して行うのと同じ方法で、これをコーダーから隠します。
グラハム

211

最初の学期では、JavaやUMLを介して、カプセル化、データ隠蔽、モジュール性、継承などのOOPの概念を紹介しました。(Javaは私の最初のプログラミング言語です)

それらはいずれもOOPの概念ではありません。それらはすべてオブジェクト指向の外部に存在し、オブジェクト指向に依存せず、オブジェクト指向の前に発明されたものも多くあります。

あなたがいることを考えるのであれば、それは OOがすべてに約あるものです、そして、あなたの結論は正しいです:あなたは、手続き型言語でそれらのすべてを行うことができ、彼らはOOとは何の関係もないので

たとえば、モジュール性に関する独創的な論文の1つは、システムをモジュールに分解する際に使用する基準についてです。そこにはオブジェクト指向に関する言及はありません。(それは1972年に書かれましたが、それまでにOOはすでに10年以上経っていますが、まだあいまいなニッチでした。)

一方でデータの抽象化はオブジェクト指向では重要であり、それはより多くのある結果、それは決定的な特徴であるよりも、OO(メッセージング)の主要な特徴の。また、データの抽象化にはさまざまな種類があることを覚えておくことが非常に重要です。今日使用されている2つの最も一般的な種類のデータ抽象化(「抽象化なし」を無視した場合、おそらく他の2つの組み合わせよりも多く使用されます)は、抽象データ型オブジェクトです。だから、ただ、「カプセル化」「情報ハイディング」、および「データの抽象化」と言って、あなたはOOのみであることから、OOについては何も言わなかった1データの抽象化の形式、および2は、実際には根本的に異なっています:

  • 抽象データ型では、抽象化のメカニズムは型システムです。実装を隠すのは型システムです。(型システムは必ずしも静的である必要はありません。)オブジェクトを使用すると、型を必要としない手続き型インターフェイスの背後に実装が隠されます。(たとえば、ECMAScriptで行われているように、クロージャーを使用して実装できます。)
  • 抽象データ型では、異なるADTのインスタンスは相互にカプセル化されますが、同じ ADTのインスタンスは互いの表現とプライベート実装を検査してアクセスできます。オブジェクトは常にすべてからカプセル化されます。オブジェクト自体のみが、独自の表現を検査し、独自のプライベート実装にアクセスできます。他のオブジェクト、同じタイプの他のオブジェクト、同じクラスの他のインスタンス、同じプロトタイプを持つ他のオブジェクト、オブジェクトのクローンなど、それを行うことができるものはありません。なし

ところで、これが意味することは、Javaではクラスはオブジェクト指向ではないということです。同じクラスの2つのインスタンスは、互いの表現とプライベート実装にアクセスできます。したがって、クラスのインスタンスはオブジェクトではなく、実際にはADTインスタンスです。JavaのinterfaceS、しかし、ないオブジェクト指向のデータの抽象化を提供します。つまり、インターフェースのインスタンスのみがJavaのオブジェクトであり、クラスのインスタンスはそうではありません。

基本的に、型については、インターフェイスのみを使用できます。これは、メソッドとコンストラクターのパラメーター型、メソッドの戻り型、インスタンスフィールド、静的フィールド、ローカルフィールドのinstanceof型、演算子またはキャスト演算子への引数、およびジェネリック型コンストラクターの型引数は常にインターフェイスでなければならないことを意味します。クラスは、new演算子の直後でのみ使用でき、他の場所では使用できません。

たとえば、モジュール性のために、プログラムを、コードが別々のファイルに含まれる明確に定義されたタスクを実行する多くの小さなプログラムに分割することができます。これらのプログラムは、明確に定義された入力と出力を介して互いに対話します。カプセル化を実現するために、ファイルを保護(暗号化?)することができます。コードを再利用するために、新しいプログラムで必要になったときにいつでもこれらのファイルを呼び出すことができます。これは、OOPが何であるかをすべてキャプチャしないのですか、それとも非常に明白な何かを見逃していますか?

あなたが説明するのオブジェクト指向です。

それは確かにオブジェクト指向について考える良い方法です。実際、OOの最初の発明者が念頭に置いていたのは、まさにそれです。(アラン・ケイはさらに一歩進んだ。彼は、ネットワークを介して互いにメッセージを送信する小さなコンピューターをたくさん構想した。)「プログラム」と呼ばれるものは通常「オブジェクト」と呼ばれ、「呼び出し」の代わりに「。

オブジェクト指向とは、メッセージング(別名動的ディスパッチ)に関するものです。「オブジェクト指向」という用語は、Smalltalkのプリンシパルデザイナーであるアラン・ケイ博士によって作られたもので、彼は次のよう定義しています

私にとってのOOPとは、メッセージング、ローカルの保持と状態プロセスの保護と隠蔽、およびすべてのものの極端な遅延バインディングのみを意味します。

それを分解しましょう:

  • メッセージング(Smalltalkに慣れていない場合は、「仮想メソッドのディスパッチ」)
  • 状態プロセスは
    • ローカルに保持
    • 保護された
    • 隠された
  • すべてのものの極端な遅延バインディング

実装上、メッセージングは​​レイトバインドプロシージャコールであり、プロシージャコールがレイトバインドである場合、設計時に呼び出す内容を知ることができないため、状態の具体的な表現について仮定することはできません。したがって、実際にはメッセージングについてであり、レイトバインディングはメッセージングの実装であり、カプセル化はその結果です。

彼は後に「大きなアイデアは「メッセージング」である」ことを明確にし、「メッセージ指向」ではなく「オブジェクト指向」と呼んだことを後悔しています。「オブジェクト指向」という用語は重要ではないもの(オブジェクト)そして、何が本当に重要なのかをそらす(メッセージング):

Smalltalkはその構文やクラスライブラリだけでなく、クラスに関するものでもないことを皆に思い出させようと、最後のOOPSLAで苦労したことを思い出してください。私がずっと前にこのトピックの「オブジェクト」という用語を作り出したことを残念に思う。

大きなアイデアは「メッセージング」です。これがSmalltalk / Squeakの核心です(Xerox PARCフェーズでは決して完成しなかったものです)。日本人は、「間にある」を意味する小さな単語maを持っています。おそらく、最も近い英語の同等語は「インタースティシャル」です。優れた成長可能なシステムを作成するための鍵は、内部のプロパティや動作がどうあるべきかではなく、モジュールの通信方法を設計することです。インターネットを考えてみてください-生きるためには、(a)単一の標準を超えたさまざまな種類のアイデアと実現を許可する必要があり、(b)これらのアイデア間のさまざまな程度の安全な相互運用性を許可する必要があります。

(もちろん、今日、ほとんどの人はオブジェクトではなくクラスに焦点を合わせていますが、これはさらに間違っています。)

メタファーとメカニズムの両方として、メッセージングはオブジェクト指向の基本です。

誰かにメッセージを送信した場合、そのメッセージをどう処理するかはわかりません。唯一のあなたが観察できる事は、その応答です。メッセージを自分で処理したかどうか(オブジェクトにメソッドがあるかどうか)、メッセージを他の誰かに転送したかどうか(委任/プロキシ)、さらに理解したかどうかはわかりません。それがカプセル化のすべて、つまりオブジェクト指向のすべてです。期待どおりに応答する限り、プロキシを本物と区別することさえできません。

「メッセージング」のより「現代的な」用語は「動的メソッドディスパッチ」または「仮想メソッド呼び出し」ですが、それは比metaを失い、メカニズムに焦点を合わせます。

したがって、Alan Kayの定義を見るには2つの方法があります。それを単独で見ると、メッセージングは​​基本的にレイトバインドプロシージャコールであり、レイトバインディングはカプセル化を意味するため、#1と結論付けることができます。と#2は実際には冗長であり、OOはすべて遅延バインディングに関するものです。

しかし、彼は重要なことはメッセージングであると後で明らかにしたので、異なる角度からそれを見ることができます:メッセージングは​​遅れている。メッセージングが唯一可能な場合、#3は簡単に当てはまります。1つだけのものがあり、その事が遅延バインディングである場合、すべてのものは遅延バインディングです。また、メッセージングからカプセル化が続きます。

同様の点は、データ抽象化の理解ウィリアムR.クックの再訪、および「オブジェクト」および「オブジェクト指向」の簡略化されたモダンな定義に対する彼の提案にもあります。

操作の動的なディスパッチは、オブジェクトの本質的な特性です。これは、呼び出される操作がオブジェクト自体の動的プロパティであることを意味します。操作を静的に識別することはできません。また、一般に、実行することを除いて、特定の要求に応じて実行される操作を正確に知る方法はありません。これは、常に動的にディスパッチされるファーストクラスの関数とまったく同じです。

Smalltalk-72では、オブジェクトすらありませんでした!解析、書き換え、および再ルーティングされたメッセージストリームのみがありました。最初に登場したのはメソッド(メッセージストリームを解析して再ルーティングする標準的な方法)、後に登場したオブジェクト(プライベートステートを共有するメソッドのグループ化)です。継承はずっと後になり、クラスは継承をサポートする方法としてのみ導入されました。Kayの研究グループが既にプロトタイプについて知っていたなら、そもそもクラスを導入したことはなかっただろう。

型とプログラミング言語の Benjamin Pierceは、オブジェクト指向の定義機能はオープン再帰であると主張しています。

Alan Kayによると、オブジェクト指向とはメッセージングに関するものです。William Cookによると、OOはすべて動的メソッドのディスパッチに関するものです(これは実際に同じことです)。Benjamin Pierceによれば、オブジェクト指向はすべてオープン再帰に関するものであり、これは基本的に自己参照が動的に解決されることを意味します(または少なくともそれを考える方法です)。つまり、メッセージングです。

ご覧のとおり、「OO」という用語を生み出した人はオブジェクトについてかなり形而上学的な見解を持ち、クックはかなり実用的な見解を持ち、ピアスは非常に厳密な数学的見解を持っています。しかし重要なことは、哲学者、プラグマティスト、理論家がすべて同意するということです!メッセージングは​​、OOの1つの柱です。期間。

ここでは継承については言及していないことに注意してください!OOには継承は必須ではありません。一般に、ほとんどのオブジェクト指向言語には実装の再利用の方法がありますが、必ずしも継承である必要はありません。たとえば、何らかの形式の委任も可能です。実際、オーランド条約では、委任は継承の代替として議論されており、異なる形式の委任と継承がオブジェクト指向言語の設計空間内の異なる設計ポイントにどのようにつながるかについて説明しています。(実際、Javaのような継承をサポートする言語でさえ、人々は実際にそれを避けるように教えられており、オブジェクト指向には不要であることを示していることに注意してください。)


16
+100-物が不適切に使用されているため、物事に固有の責任を負います。
JeffO

55
申し訳ありませんが、これは非常に間違っています。アラン・ケイはこの言葉を思いついたかもしれませんが、その原則はSmalltalkの前にありました。オブジェクト指向プログラミングはSimulaから派生しており、そのOOスタイルは「メッセージ」とは何の関係もありませんでした。成功しているほとんどすべてのOO言語は、Simulaで規定されている基本原則(Javaで見られるものと同じ)で実行されています。また、SmalltalkスタイルのOOは、再導入されるたびに「アイデアの市場」で失敗しています。まったくうまく機能しないからです。名前はケイが貢献した唯一の本当に意味のあるものでした。
メイソンウィーラー

23
@steakexchangeいいえ。「OOの本質」、それを本当に際立たせるものは、仮想メソッドを持つオブジェクトです。誰もSmalltalkを使用しない理由があります。メッセージパッシングシステムは、個々のコンピュータースケールでは非常にうまく機能しません。善意の、しかし素朴な言語デザイナーがSmalltalkの原則を再実装しようとするたびに、失敗に終わります。(最新の例はObjective-Cで、Steve JobsがiOSコミュニティの喉全体に押し付けなかったなら誰も使用しなかったでしょう。Appleエコシステムの外で何の牽引力も見つけられず、その理由があります。 )
メイソンウィーラー

28
@MasonWheelerヨルグが言っていることとは正反対の見方をしているので、答えのコメントについて詳しく説明していただけますか?
ステーキ交換

20
また、オブジェクト指向言語の概念が大きく進化したことにも注意してください。これらの先祖概念は、多くの言語が古いモデルを捨て、マルチパラダイムを採用している今日、それほど真実ではないかもしれません。たとえば、C#を見てください。この言語は、太陽の下でほとんどすべてを一度に混同し、ほとんどがOO言語と呼ばれますが、実際には異なるパラダイムの混合です。これにより、すべての開発者にとって非常に表現力豊かなツールになります。また、クラスベースのオブジェクト指向は、オブジェクト指向プログラミングの同様に有効なフレーバーの1つです。
T. Sar

66

しかし、モジュール性、カプセル化、データ隠蔽などの複雑さを管理するために使用されるすべての原則は、手続き型言語によって非常に簡単に実装できると思います。

「非常に簡単」と言うと、非常に大胆な発言をしていることになります。読み方は「難しさは見えないので、それほど大きくてはいけない」です。そのように表現すると、「なぜOOが必要なのか」ではなく、「なぜOOの発明につながる他のプログラミングパラダイムが直面した困難がないのか」と尋ねていることが明らかになります。 」

その質問への答えは、これらの困難の多くはあなたが取り組んでいる種類のプログラムには存在しないということです。40年前のスパゲッティコードを更新するよう求められていません。オペレーティングシステム用の新しいディスプレイマネージャを作成しようとはしていません。マルチスレッドの分散アプリケーションをデバッグしていません。

CSの学生が書くことを任されている多くの種類のおもちゃプログラムについては、JavaまたはPythonのようにBASICまたはアセンブリで書くこともできます。これは、タスクの固有の複雑さが非常に低く、開発者が1人だけであり、レガシーな相互運用性の問題がなく、パフォーマンスが重要でなく、コードが1台のマシンで数回しか実行されないためです。

学生ドライバーを連れて、ラッシュアワーの混雑した通りに、シンクロメッシュのない手動変速機で、急な坂を上って行くように頼むことを想像してください。災害。どうして?彼らは、タスクが必要とするすべてのルールを同時に守るために必要な複雑さのレベルを管理することができません。

ここで、同じ学生、同じ車両が、空いている駐車場で歩いているペースで運転していると想像してください。彼らのスキルのレベルはタスクに十分であるため、彼らは大丈夫です。プレッシャーはなく、リスクはほとんどありません。彼らは個々のサブタスクを開始、クラッチ、シフト、加速、一度に1つずつ操縦することができます。

その学生は、熟練したドライバーがこれらすべてを同時に行うことができる場合、なぜ自動変速機があるのか​​と尋ねるかもしれません。答えは、熟練した十分なドライバーは、最適な状況では自動を必要としないということです。しかし、私たちはすべてが最高の状態にあるプロのドライバーではないので、通常、車のデザイナーにそのような複雑さをすべて処理してもらう便利さを求めています。

熟練した訓練された十分なプログラマは、実際にCまたはアセンブリで機能する複雑度の高いシステムを作成できます。しかし、私たちはすべてLinus Torvaldsではありません。有用なソフトウェアを作成するために、そうする必要もありません。

私は、手近にある問題に対処する前に、現代言語のすべての機能を再発明しなければならないことに個人的に興味はありません。すでに解決された問題の解決策を含む言語を利用できる場合、なぜそうしないのでしょうか?

カプセル化やポリモーフィズムなどの便利な機能を言語が提供するのであれば、なぜそれらを使用してはいけないのでしょうか?


13
したがって、基本的に手続き型言語でオブジェクト指向を行うことは可能ですが、標準化されたオブジェクト指向言語を使用して手動で物事を行うことで、自動化および簡素化されます。
ステーキ交換

6
@steakexchangeまさにそれ。
ティムB

3
@steakexchangeの歴史的な好例は、当時のX Windowsのオブジェクトモデルでした。Cで書かれましたが、オブジェクト指向システムに基づいていました。そのため、クラスが他のすべてのクラスでうまく動作するように、特定の規則に従ってインターフェイスを使用する必要がありました。
ウッコ

7
@nocomprende確かに。しかし、一つは、可能性がある RAWディスクを実行して起動できなく自分のコンピュータをレンダリングするファイルシステムに頼るのではなく、書き込み、およびそこになります初心者で構築されたアドホック対象システムでの問題のデバッグに本当に難しいこと。カプセル化は、正しく行われると、意図的または意図せずに行うべきではないことを妨げます。
クレメントチャーリン

3
オブジェクト指向の恩恵を受けるアプリケーションの例がオブジェクト指向言語で書かれていないことは、私にとって興味深いことです。40歳のスパゲッティはおそらくC、COBOL、FORTRANまたはREXXで書かれています。ディスプレイマネージャは、おそらく(OO-ISH規則はあるものの)、Cで書かれ、そして多くの成功した分散型マルチスレッドシステムはErlangで書かれている、移動またはC.
James_pic

22

あなたが説明しているのはOOPではなく、抽象化です。抽象化は、OOPではないものも含め、現代のすべての設計モデルに存在します。そして、OOPは非常に特殊な抽象化です。

まず、OOPの定義が1つしかないことは注目に値します。そのため、私がOOPとして特徴付けていることに同意しない人がいるかもしれません。

第二に、OOPは従来の設計モデルに触発されたことを覚えておくことが重要です。したがって、車の設計との類似性は偶然ではありません。

ただし、OOPがあなたが言ったことよりも微妙な方法がいくつかあります。

  • カプセル化:これは、モジュールのセットインターフェイス(抽象化)だけでなく、このインターフェイスを超えたアクセスを禁止することでもあります。Javaでは、プライベート変数へのアクセスはコンパイルエラーですが、車の設計では(場合によっては)意図したインターフェイスとは異なる方法で使用できます。

  • 継承:これは本当にOOPをユニークにするものです。インターフェイスを定義したら、そのインターフェイスを実装する複数のことを行うことができます。これを階層的な方法で行い、実装の特定の部分を変更しながら、以前のすべての部分を継承し、コードの重複を大幅に削減できます。

    車のカプセル化されたコンポーネントの観点から考えると、実際にこれに相当するものはありません。別のギアを取り、その実装の特定の部分を変更してギアを作成する方法はありません。(少なくとも私はそうは思わない、私は車についてあまり知らない)。

  • ポリモーフィズム:インターフェースを定義したら、そのインターフェースを使用するものは、利用可能な操作の観点から見分けがつかないはずであり、インターフェースを使用するためにどの実装が使用されているかを知る必要はありません。これは、サブタイピングとリスコフ代替原理が重要になる場所です。

  • カップリング:OOPの重要な側面は、物事を同じ操作に密接に関連付け、それらが持つことができるさまざまな形式を広げることです。データには、そのデータに対する操作がバンドルされています。つまり、新しい形式のデータを追加するのは非常に簡単ですが(新しい実装)、インターフェイスに新しい操作を追加するのは非常に困難です(インターフェイスを実装する各クラスを更新する必要があるため)。これは関数型言語の代数データ型とは対照的です。関数型言語では、新しい操作を追加するのは非常に簡単です(すべてのケースを処理する関数を書くだけです)が、新しいバリアントを追加するのは難しいです(新しいものを追加する必要があるため)すべての機能のケース)。


1
いい答えだ!私が同意しない部分:カプセル化についてあなたが描いている区別は無効です。カプセル化は、常に「このインターフェースを超えたアクセスを禁止する」ことを意味します。これは、OOP設定と非OOP設定の両方に当てはまります。したがって、この部分はOOP固有のものではありません。
DW

@DW私はこれを明確にしようとしました。OOPに固有のものではなく、カプセル化と抽象化の違いだと言います。フィードバックをお寄せいただきありがとうございます!
jmite

2
OK。しかし、私はここでその主題について何が書かれているかについて、まだ別の見方をしています。「OOPがあなたが言ったことよりもニュアンスのある方法がある」と書いたが、カプセル化はOOPが質問で書かれたものよりもニュアンスのある方法ではない。カプセル化は、どのようなパラダイムでもそうです。そして、「あなたが記述しているのはOOPではなく、抽象化である」と書いたところで、元の質問はカプセル化(抽象化だけでなく)を記述しようとしていると思いました。私はこのコメントを別の視点として残すだけだと思います。答えはとても役立つと思います!
DW

継承は一般的な機能ですが、いくつかの重要なオブジェクト指向言語にはそれがありません。
ブラッドゾニエ17年

良い答えですが、IMOは車の例を誇張しています。特定のモデルのエンジンには、明確に定義されたインターフェイス(カムシャフト、取り付けブラケット "レセプタクル"など)があります。普通の古いキャブレターを燃料噴射式のキャブレターに交換したり、ターボチャージャーを追加したりするなど、トランスミッションに影響を与えることなく使用できます。(ただし、ディーゼルエンジンには変更された燃料タンクIIRCが必要です。)逆に、手動変速機を、エンジンにまったく影響を与えない自動およびAFAIKに置き換えることができます。
デビッド

11

ソフトウェアの複雑さを管理するためにオブジェクト指向言語が本当に必要ですか?

これは、「必要」という言葉の意味に依存します。

「必要」が「必要」を意味する場合、必要ありません。

「必要」が「強力なメリットを提供する」ことを意味する場合、「はい」と言います。

大局

オブジェクト指向言語は、機能をデータにバインドします。

このバインディングを回避し、データ値を渡す関数を作成できます。

しかし、その後、データのコンステレーションが一緒になって、データのタプル、レコード、またはディクショナリをやり取りし始めるでしょう。

そして実際、それはすべてのメソッド呼び出しです:バインドされたデータセットの部分関数。

機能ごと

OOPの機能:

  • 継承により、コード(ミックスイン)およびコンセプト(抽象基本クラス/インターフェース)の再利用が可能になりますが、サブスコープで関数と変数を再装飾することでこれを実現できます。
  • カプセル化は情報の隠蔽を可能にするため、より高い抽象化レベルで作業できますが、ヘッダーファイル、関数、およびモジュールを使用してこれを行うことができます。
  • 多態性は、それらの引数が同じインターフェースをサポートしている限り、異なるタイプの引数を使用することを可能にしますが、関数でも同様に行うことができます。

ただし、これらの機能は、これらの機能をファーストクラスでサポートするオブジェクト指向言語の場合ほど簡単には起こりません。

参照資料

OOPには多くの批評家がいます。

ただし、調査によると、OOPを使用したコードの再利用により、プログラマの生産性が向上しているようです。これは議論の余地のある発見であり、特定の制約があるため、これらの生産性の向上を再現できないと言う研究者もいます。(ソース)

結論

OOPは「必要」ではありません。しかし、場合によっては、ユーザー OOPを必要とします。

私の理解では、成熟したプログラマーはオブジェクト指向スタイルで非常に生産的であり得るということです。また、パッケージに簡単に理解できるシンプルなインターフェイスを備えたコアオブジェクトがある場合、新しいプログラマでもすぐに生産性を高めることができます。


10

簡単に説明します。

OOの基本原則は、単一の組織単位(オブジェクト)におけるデータと動作の組み合わせです。

これは複雑さを制御することを可能にするものであり、出現したときはかなり革新的な概念でした。それを一方でファイル(純粋なデータ)と比較し、他方でそれらのファイルを読み取って処理するプログラム(純粋なロジック)および出力(再び純粋なデータ)と比較してください。

現実世界のエンティティをモデル化して、データとロジックのパッケージを一緒に持って初めて、メッセージの交換を開始し、子クラスを作成し、パブリックデータと動作からプライベートを分離し、多態的な動作を実装し、このOO固有の魔法をすべて実行できます。

それで、はい、オブジェクト指向は大したことです。そして、いや、それは単なる派手な名前の古いものではありません。

それをすべて分解し、要素を見てから「ああ、まあ、これまで見たことのないものは何もない」と言うことは、イノベーションを保持するアセンブリを認識していません。結果は、その部分の合計以上です。


8

オブジェクト指向プログラミングの「公式」定義はなく、合理的な人々は実際にオブジェクト指向の品質を定義していることに同意しません。メッセージングを言う人もいれば、サブタイプを言う人もいれば、継承を言う人もいれば、データと動作の束ねを言う人もいます。これは、この用語が無意味であることを意味するのではなく、実際のオブジェクト指向とは何かについて口論するのに追いつくべきではありません。

カプセル化とモジュール性は、設計のより基本的な原則であり、すべてのプログラミングパラダイムに適用する必要があります。OOの支持者は、これらの特性はOOでのみ達成できると主張していません。OOがこれを達成するのに特に適しているということだけです。もちろん、関数型プログラミングなどの他のパラダイムの支持者は、パラダイムについても同じことを主張しています。実際には、成功している多くの言語はマルチパラダイムであり、オブジェクト指向や機能などは「1つの真の方法」ではなくツールと見なされるべきです。

複雑さを管理するために使用されるすべての原則は、手続き型プログラミング言語によって実現できると思います。

確かに、最終的にはあらゆるプログラミング言語で何でもできるからです。すべての言語には長所と短所が異なるため、一部の言語では他の言語よりも簡単です。


7

他の答えが言及していないもの:状態。

複雑さを管理するためのツールとしてオブジェクト指向についてお話します。複雑さは何ですか?それはあいまいな用語です。私たちは皆、それが何を意味するのかというこのゲシュタルト感覚を持っていますが、それを突き止めるのは難しいです。循環的な複雑さ、つまりコードを通る実行時パスの数を測定できますが、OOを使用して複雑さを管理しているとき、それが何を言っているのかわかりません。

私たちが話していると思うのは、状態に関連した複雑さです。

カプセル化の後ろに2つの主な考えがあります。それらの1つである実装の詳細の非表示は、他の回答でかなり詳しく説明されています。しかし、もう1つは実行時の状態を隠しています。オブジェクトの内部データをいじりません。メッセージを渡します(または、JörgMittagが指摘したように、概念よりも実装の詳細を好む場合はメソッドを呼び出します)。どうして?

既に言及しているのは、アクセスするコードを変更せずにデータの内部構造を変更することはできず、それを300箇所ではなく1箇所(アクセサメソッド)で行いたいためです。

しかし、それはまた、コードの推論を難しくするためでもあります:手続き型コード(本質的に手続き型であるか、単にそのスタイルで書かれている言語であるかどうか)は、状態の突然変異に制限を課すのにほとんど役立ちません。どこからでもいつでも何でも変更できます。関数/メソッドの呼び出しには、不気味なアクションがあります。テストの成功は、広くアクセス/アクセス可能な非ローカル変数の値によって決定されるため、自動テストはより困難です。

他の2つの大きなプログラミングパラダイム(OOと機能)は、興味深いが、状態に関連する複雑さの問題に対するほぼ正反対のソリューションを提供します。関数型プログラミングでは、それを完全に回避しようとします。関数は一般的に純粋であり、データ構造に対する操作は元の場所を更新するのではなくコピーを返します。

一方、OOは状態を管理するためのツールを提供します(回避するためのツールの代わりに)。アクセス修飾子(保護/パブリック/プライベート)、ゲッター、セッターなどの言語レベルのツールに加えて、オブジェクトを介して他のオブジェクトデータに到達することを禁止するデメテルの法則などの関連する規則も多数あります。 。

これを実際に行うためにオブジェクトは必要ないことに注意してください。アクセスできないデータを持ち、それを操作する関数のデータ構造を返すクロージャを作成できます。しかし、それはオブジェクトではありませんか?これは、オブジェクトが何であるかの概念に直観的に適合しませんか?そして、この概念がある場合、競合するアドホックな実装の組み合わせの爆発に依存するよりも(他の回答が言っているように)言語でそれを再定義する方が良いのではないでしょうか?


5

ソフトウェアの複雑さを管理するためにオブジェクト指向言語が本当に必要ですか?

いいえ。 しかし、多くの状況で役立ちます。

何十年もの間、主に単一のオブジェクト指向言語を使用してきましたが、実際には、ほとんどのコードは厳密にオブジェクト指向スタイルより前の手続きです。ただし、GUIに関係するものについては、言語の膨大な組み込みメソッドとオブジェクトのOOライブラリを使用します。コードが非常に単純化されるからです。

たとえば、元の低レベルWindows APIを使用してフォーム、ボタン、および編集フィールドを表示するWindowsアプリケーションは、多くのコードを必要としますが、代わりにVisual BasicまたはC#またはDelphiに付属するオブジェクトのライブラリを使用して、小さくて些細なプログラム。したがって、私のOOコードは通常比較的小さく、GUI向けですが、これらのオブジェクトが呼び出す私のコードは通常はるかに大きく、通常はオブジェクト指向であることには関係ありません(ただし、解決しようとしている問題によって異なります)。

オブジェクト指向のプログラムは、非常に複雑で、オブジェクトの実装方法に関する複雑な難解なルールに依存しており、オブジェクト指向の概念なしで記述すれば、はるかに簡単になります。私は反対も見ました。オブジェクトを使用して複雑なシステムを再実装および単純化するように叫びます。

経験を積むにつれて、さまざまな状況でさまざまなツールとソリューションが必要になり、1つのサイズがすべてに適合するわけではないことがわかります。


3

完全にCで書かれた非常に大きなプロジェクトに関与している人として、私は間違いなく答えは明確な「いいえ」であると言うことができます。

モジュール性が重要です。しかし、モジュール性は、実際にはあらゆる適切な言語で実装できます。たとえば、Cはモジュラーコンパイル、ヘッダーファイル、および構造タイプをサポートしています。これは、99%のケースで十分です。必要な新しい抽象データ型ごとにモジュールを定義し、データ型を操作するための関数を定義します。パフォーマンスが必要な場合があり、それらの関数はインライン関数としてヘッダーファイルに含まれていますが、標準関数を使用する場合もあります。どの方法が選択されているかは、ユーザーにはすべて見えません。

構造は構成をサポートします。たとえば、相互排他ロックと通常のハッシュテーブルで構成されるロックされたハッシュテーブルを持つことができます。これはオブジェクト指向プログラミングではありません。サブクラス化は行われません。コンポジションは、オブジェクト指向プログラミングの概念よりもはるかに古いツールです。

コンパイルレベルのモジュール性が十分ではなく、実行時のモジュール性が必要な場合の1%には、関数ポインターと呼ばれるものがあります。これらは、明確に定義されたインターフェースの個別の実装を可能にします。これは、非オブジェクト指向言語のオブジェクト指向プログラミングではないことに注意してください。これは、インターフェースを定義してから実装しています。たとえば、ここではサブクラス化は使用されません。

おそらく最も複雑なオープンソースプロジェクトを考えてみてください。つまり、Linuxカーネル。完全にC言語で書かれています。これは、主に構成を含む標準のコンパイルレベルのモジュールツールを使用して行われ、実行時のモジュールが必要な場合は常に、関数ポインターを使用してインターフェイスを定義および実装します。

Linuxカーネルでオブジェクト指向プログラミングの例を見つけようとすると、「インターフェイスを定義してから実装する」などの標準タスクを含めるようにオブジェクト指向プログラミングを拡張しない限り、そのような例を見つけるのは非常に難しいでしょう。

Cプログラミング言語でも、本当に必要な場合はオブジェクト指向プログラミングをサポートしていることに注意してください。たとえば、GTKグラフィカルユーザーインターフェイスツールキットを検討してください。非オブジェクト指向言語で書かれていますが、実際にはオブジェクト指向です。したがって、これは、「オブジェクト指向言語」が必要であるという考えが非常に欠陥があることを示しています。オブジェクト指向言語でできることは、他の種類の言語ではできないことではありません。さらに、あなたが熟練したプログラマーであれば、どの言語でもオブジェクト指向コードを非常に簡単に書く方法を知っています。たとえば、Cを使用しても負担になりません。

したがって、結論は、オブジェクト指向言語は、概念が実際にどのように実装されているかを理解していない初心者プログラマーにのみ有用である可能性が高いということです。ただし、プログラマーがそのような初心者プログラマーであるプロジェクトの近くにはいたくありません。


1
「[...]結論は、オブジェクト指向言語はおそらく、概念が実際にどのように実装されているかを理解していない初心者プログラマーだけに役立つということです。」面白い。どの言語を考えていますか?これらの言語で書かれた、失敗した、または失敗しなかったオープンソースプロジェクトの例はありますか?
ビンセントサバード

3
あなたはいくつかの良い点を挙げますが、あなたの主な考えには欠陥があります。はい、カプセル化、仮想ディスパッチ、継承、さらにはガベージコレクションなどのオブジェクト指向の概念をCなどの言語で実装することができます。それをアセンブリで行うこともできます。プログラミングが簡単になるわけではありません。Cのような言語でのプログラミングと特に設計は、OO言語の場合よりも間違いなく困難です。Cでは、概念を実装にマップする必要がありますが、OO言語では、そのステップを実行する必要はありません(少なくともOOの概念については)。
fishinear

1
「[関数ポインタ]により、明確に定義されたインターフェイスの個別の実装が可能になります。これは、非オブジェクト指向言語のオブジェクト指向プログラミングではないことに注意してください。これはインターフェイスを定義して実装します。」申し訳ありませんが、これは完全に間違っています。これがまさに OOP であるためです。「たとえば、サブクラス化はここでは使用されません」サブクラス化はOOPの必須機能ではありません。たとえば、JavaScriptはオブジェクト指向言語であり、サブクラス化(または、その点ではクラス...機能参照を含むオブジェクトのみ)を特徴としないことに注意してください。
ジュール

1
私の最後のコメントを明確にするために、私のポイントは、OOP(必ずしも特定のOO言語である必要はない)と他のメソッドの主な区別要因は、OOPでデータの形式を知らなくてもデータを抽象的に操作するインターフェースを定義することですインターフェースの実装をデータ自体にバインドします。それがOOPです。実装方法は、Javaスタイルクラス、JavaScriptオブジェクト(事実上、名前と属性のマップ、データまたはコードのいずれか)、または関数ポインターとデータのvoid *を含む構造であるかどうかに関係ありません。
ジュール

1
「だから、結論は、オブジェクト指向言語はおそらく、概念が実際にどのように実装されているかを理解していない初心者プログラマーだけに役立つということです。」そして、これは率直に言って、plain辱です。これらの概念がどのように実装されているかを十分に知っています。でも、それを使って十分な仕事をして、上手になりました。過去にオブジェクト指向言語用のインタープリターとコンパイラーの両方を実装しました。しかし、私はファーストクラスのオブジェクトを持っている高レベルの言語で働くことを好むので、私はあなたが一緒に仕事をしたくないという初心者プログラマでなければなりませんか?!
ジュール

2

オブジェクト指向メソッドを含むプログラミングパラダイムを導入する理由は、より洗練された強力なプログラムを簡単に作成できるようにするためです。Byte Magazineの1981年8月号で、Smalltalkの主要な作成者の1人であるDaniel Ingallsは、「オブジェクト指向」を次の機能を含むと定義しました。

  • 自動ストレージ管理
  • メッセージを交換する能力
  • 言語のすべての操作に適用される統一メタファー
  • 別のコンポーネントの内部に依存するコンポーネントはありません(モジュール性)
  • プログラムはオブジェクトの動作のみを定義し、オブジェクトの表現(多態性)は定義しません
  • 各コンポーネントは1か所にのみ表示されます(ファクタリング)
  • ハードウェアに依存しない仮想マシンの使用
  • ユーザーがアクセス可能なすべてのコンポーネントは、監視と制御に使用できる必要があります(反応原理)
  • 全体的なコントローラーはありません(オペレーティングシステムはありません)

これらは、Xerox Parc Researchが開発したSmallTalk-80の駆動設計の考慮事項としてインガルズが特定した原則でした。前述の雑誌の記事では、これらの原則のそれぞれの詳細な説明と、それらがインガルズによるオブジェクト指向のパラダイムにどのように貢献しているかを読むことができます。

これらのすべての原則は、手続き型、アセンブリ言語など、チューリング完全言語を使用して適用できます。これらは設計の原則であり、言語の仕様ではありません。オブジェクト指向言語は、ソフトウェアを作成するときにこれらの原則を使いやすくすることを目的としています。

たとえば、Ingallの原則(自動ストレージ管理)の最初の原則を採用するために、誰でも手続き型言語で独自の自動ストレージ管理システムを作成できますが、そうするのは大変な作業です。SmallTalkやJavaなどの自動ストレージ管理が組み込まれた言語を使用する場合、プログラマはメモリを管理するためにそれほど多くの作業を行う必要はありません。トレードオフは、プログラマがメモリの使用方法をあまり制御できないことです。そのため、利点と欠点があります。オブジェクト指向プログラミングのような設計パラダイムの考え方は、少なくとも一部のプログラマーにとって、パラダイムの利点が欠点を上回るということです。


ドメイン固有言語の場合にも同じ規則が適用されると思います。同じ長所と短所... 1つの違いは、「言語」は問題空間の理解に対応し、他には何も含まれていないため、DSLをエンドユーザーが操作できるほど簡単にできることです。

0

ソフトウェアの複雑さを管理する1つの方法は、Domain Specific Languageを完全に使用して必要な動作からフレームワークを切り離すことです。これは、プログラミングコードのレベルが、目的の結果が構成されているレベルとはまったく異なることを意味します。完全に異なる言語またはシステムです。これが適切に行われると、従来のコードは本質的にライブラリになり、目的の結果を作成するユーザーまたは他の人は、スクリプトジェネレーターやレポートジェネレーターなどの視覚的なデザインツールで物事をつなぎます。

これを機能させるには、どの操作が可能か、どのようにリンクするか(フォーム作成ツールのようなスクリプト言語または視覚的なデザイン)について厳密な境界線を引く必要があります。メタデータは、コーディングの詳細からランタイム構成を抽象化する重要な方法であり、システムが幅広い望ましい結果をサポートできるようにします。境界がレイアウトされて保持されている場合(付随する拡張機能のすべての要求を受け入れない場合)、人々が望むことを達成するためにプログラマである必要なく、人々のために機能する、長持ちする堅牢なシステムを使用できます。

マーティン・ファウラーはこれについて本を書いており、その手法はプログラミング自体とほぼ同じくらい古いです。すべてのプログラミング言語はドメイン固有言語であるとほぼ言えるでしょう。したがって、このアイデアは風土病であり、非常に明白であるため見過ごされています。ただし、独自のスクリプト作成ツールや視覚的なデザインツールを作成して、生活を楽にすることもできます。問題を一般化すると、解決がはるかに簡単になることがあります!


0

これは非常に良い質問であり、ここで与えられた答えは正義を行っていないと感じているので、先に進んで自分の考えを追加します。

目的は- ソフトウェアの複雑さを管理することです。目的は「OO言語を使用する」ことではありません。

新しいパラダイムを導入する背後にある「理由」はありません。コーディングがより成熟するにつれて、それは自然に起こりました。リンクリストの最後に新しいノードを追加するよりも、トレイン(リンクリストを使用してモデル化される列車)の最後にコーチを追加するコードを記述する方が合理的です。


現実世界のエンティティに関するコーディングは、現実世界のエンティティについてコーディングしているときにコーディングするための明確で正しい方法です。


コンピューターは、列車の最後に追加のコーチを追加するのと同じくらい簡単に、リンクリストの最後にノードを追加することができます。ただし、人間にとっては、リンクリストとノードを使用するよりも、列車とコーチを使用する方が簡単です。レベルを深くすると、リンクリストを使用して列車がモデル化されます。

ファイルを保護または暗号化しても、カプセル化を達成できません。暗号化の反対は復号化です。カプセル化の反対はカプセル化解除です。これは、プログラミング言語の構造とクラスを分解してパフォーマンスを向上させることを意味します。メモリトラフィックを削減し、OOPルールチェックを回避することでパフォーマンスが向上しました。

したがって、これら2つは異なる概念であるため、暗号化され、適切にカプセル化されたコードを作成できます。

カプセル化は、現実に近いため、複雑さを管理するのに役立ちます。

したがって、オブジェクトをプログラムするのは、コーディングが簡単であり、自分と他のすべての人が理解しやすいためです。


0

覚えておくべきことの1つは、
OOPは言語機能に関するものではありません。コードの構造についてです

OOPは思考の方法であり、コードのアーキテクチャを設計する方法であり、ほぼすべての言語で実行できます。これには特に、アセンブラーとCと呼ばれる低レベルの非OO言語が含まれます。アセンブラーで完全にオブジェクト指向のプログラミングを行うことができ、Cで記述されたLinuxカーネルは多くの面で非常にオブジェクト指向です。 。

とは言っても、言語のオブジェクト指向機能は、目的の結果を達成するために記述する必要のある定型コードの量を大幅に削減します。仮想関数テーブルを明示的に定義し、Cで適切な関数ポインターで埋める必要がある場合は、Javaで何もなくても完了です。OO言語は、ソースコードからクラフティングを可能にするものをすべて削除し、言語レベルの優れた抽象化(クラス、メソッド、メンバー、ベースクラス、暗黙的なコンストラクタ/デストラクタ呼び出しなど)の背後に隠します。

そのため、OOPを行うのにオブジェクト指向言語は必要ありません。まともなオブジェクト指向言語を使用すると、OOPがはるかに簡単になります。


-1

オブジェクト指向プログラミングは、単なるモジュール+カプセル化以上のものです。あなたが言うように、非オブジェクト指向(手続き型)言語でモジュール+カプセル化を使用することが可能です。OOPにはそれだけではなく、オブジェクトとメソッドが含まれます。だから、いや、それはOOPをキャプチャしません。たとえば、https://en.wikipedia.org/wiki/Object-oriented_programmingまたは優れた教科書のOOPの紹介を参照してください。


答えてくれてありがとう。お勧めしますか?
ステーキ交換

-2

最大の理由は、プログラムがより複雑になると、その一部を他の部分から見えないようにする必要がある、またはアプリの複雑さと機能の数があなたの脳をあなたの耳から垂れさせることです。

100クラスのシステムを想像してみましょう。各クラスには、約20の操作を実行できます。2,000個の関数です。ただし、そのうち、「保存」や「削除」などの完全な操作は500個だけであり、1500は少しのメンテナンスを実行するか、何らかのユーティリティの役割を持つ内部機能です。考慮してください。

// intentionally in a non-specific language!

setName(person, name) {
    nameParts = splitPersonName(name);
    person.firstName = nameParts[0];
    person.lastName = nameParts[1];
    person.modified = true;
}

splitPersonName(name) {
    var result = [];
    result.add(name.substring(0, name.indexOf(" ")));
    result.add(name.substring(name.indexOf(" ") + 1));
    return result;
}

だから、SetName人々がやるべき機能である人物が、SplitPersonName使用されるユーティリティ関数ですによって人。

単純な手続き型プログラミングでは、これら2つの操作を区別しません。つまり、2,000の機能がすべて注目を集めます。ただし、これらの機能を「個人レコードを持つすべての人が利用できる」とマークし、「個人レコード内のユーティリティ機能としてのみ使用する」とマークできる場合、500個の「すべての人が利用できる」機能と15個の「ユーティリティ」が注目されます編集しているクラスの関数。

それが何でpublicあり何をするprivateかです。

public class Person {
    public void setName(...) {...}
    private string[] splitPersonName(...) { ...}
}

1
私の質問を正しく理解しているかどうかわかりません。複雑さを管理する方法として、カプセル化とデータの隠蔽を既に知っています。これは手続き型言語でも簡単に行えると思います。プログラムを、明確に定義された単純なタスクを実行するモジュールに分割することで、その内部の動作は別の保護されたソースで指定されます。では、なぜ手続き型言語でそれらのことができるのにOOPなのでしょうか?それが私の質問です。
ステーキ交換

2
私の答えは、この種のことをしたい場合は、特別なツールと言語構成を作成する必要があると思います(たとえば、インクルードしないファイルを含む特別な「インクルード」呼び出し他の場所に含まれる)。そのパスを開始すると、実際に独自の方法でオブジェクト指向言語の実装を開始しました。たとえば、C ++となった元々のプレーンCを生成するプリプロセッサ、あなたのシステムを実装していたら、それはC.の上にC ++のようにたくさん見える、と私は疑い
user62575

3
@steakexchange OOPは、多くの手続き型言語にそのようなモジュールがなかった時代に開発されたことに注意してください。そのような言語を手続き型とさえ呼ばない人もいます。実際、手続き型言語がオブジェクト指向であってはならない、またはその逆であってはならないということは何もありません。ラベルに注意してください-簡単に誤解を招く可能性があります。手続き型言語がパブリックフィールドとプライベートフィールドおよびプロシージャを備えたモジュールをサポートしている場合:)「従来の手続き型」と「OOP」の主な違いは、コールディスパッチがOOPでより柔軟であることです。実際、厳密なOOPでは、どんなコードを呼び出すのか分からない
ルアーン

2
@steakexchange MLファミリ言語では、モジュールは優れた機能を発揮し、ラムダと組み合わせることで、あらゆるOO言語のすべてのパワーを提供します(結局、関数は単一のメソッドを備えたインターフェイスです-推奨されることはほとんどありません)オブジェクト指向の「良いコード」の人?:P)。さまざまな理由で、C ++やJavaなどのより手続き型の言語よりもまだ使用されていませんが、魅力があり、多くの人々は、どのように人生を簡略化できるかについて人々に教育しようとしています(多かれ少なかれ成功しています)。
ルアーン

Cにはこれらの効果があります。インターフェイス(.hファイル)を備えたモジュール(.cファイル)があり、パブリック(外部)および非パブリック(外部)メソッド(関数)を持つことができます。あなたも、関数ポインタの配列と貧乏人の多型を持つことができ、私はOOはCで簡単に(あるいは、SANE)であるが、カプセル化は、非常に簡単ですとは言わないよ
ニック・キースリー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.