web-dev-qa-db-ja.com

手続き型プログラムとオブジェクト指向プログラムの違いは何ですか?

私はプログラミングにかなり慣れていませんが、さまざまなプログラミングアプローチについてStackOverflowに関する興味深い議論をいくつか読んでいます。手続き型プログラミングとオブジェクト指向プログラミングの違いはまだ100%わかりません。オブジェクト指向プログラミングはまだ手順(メソッド)を使用しているように聞こえますが、オブジェクトがショーのスターであるため、すべてが異なる方法で構成されています。しかし、手順を実行しても、同じことをすべて実行できるように思えます。 Cと同様に、類似したすべてのプロシージャをライブラリに入れることができます。では、CのライブラリはC++のオブジェクトに似ているとは本当に言えないのでしょうか。

29
Kerzin

2つの違いは微妙ですが重要です。

手続き型プログラムでは、モジュールは、共有データ構造に格納されている状態の読み取りと書き込みによって相互作用します。

オブジェクト指向プログラムでは、オブジェクト形式のモジュールは、他のオブジェクトにメッセージを送信することによって相互作用します。

13
Serx

手続き型プログラムでは、コードは王様であり、データは従属です。言い換えれば、データに作用するプログラムがあり、それらは通常、緊密にバインドされていません。

OO=世界では、オブジェクトが主な関心事です。オブジェクトはデータで構成されていますandそのデータに作用することが許可されているコードであり、それらは非常にそれは、カプセル化、つまり情報の隠蔽の概念です。

例として、数値があり、それを2倍にしたいとします。これを行う手順は次のとおりです。

_n = n * 2
_

ここのコードは、nを2倍に明示的に乗算し、結果をnに格納しています。

OOこれを行う方法は、数値オブジェクトに「メッセージ」を送信して、それ自体を2倍にするように指示することです。

_n.double();
_

この利点は、ポリモーフィズムと呼ばれます。 "bob"のような文字列を2倍にしたい場合、どうなりますか。手続きの世界では、倍加を行うためにより多くのコードを提供する必要がありますが、そのコードを別の方法で呼び出す必要もあります。

OOでは、「double」メッセージも受け取ることができる文字列オブジェクトを作成します。文字列を2倍にするコードは文字列オブジェクトに属しているため、数値オブジェクトとは異なる動作をする必要があることがわかります。 「bob」* 2が「bobbob」であると判断した場合、コードは次のようになります。

_class number:                    class string:
    int n                           char array s
    procedure double:               procedure double:
        n = n * 2                       s = string_join(s,s)
_

次に、実際のx型(数値または文字列)に関係なくx.double()を呼び出すことができ、実行するコードがわかります。これにより、コードが大幅に簡略化されます。モニターでは、整数、文字列、行列、複素数、実数、ウィンドウサイズなど、さまざまなものを2倍にできます。

そして、そうです、Cライブラリはオブジェクトのように見えるように作成できます。古典的な例は_stdio.h_です-あなたは気にしませんwhat _FILE*_は実際に指しますが、特定の方法で動作するという事実だけです。 _FILE*_、fopen()fclose()およびその他の関数は、CのI/O機能を表す種類のクラスです。

34
paxdiablo

ほとんどのOO言語で手続き的にプログラミングできますが、OOの力は、その手続き型ロジックを継承、カプセル化、抽象化する能力に由来します。私はあなたがライブラリはクラスによく似ているはずです。ライブラリには独自のスコープがあり、意味のある名前の関数の背後にあるロジックをカプセル化する必要があります。

21
Aram Verstegen

オブジェクト指向プログラムは多くの点で手続き型パラダイムに基づいているというあなたの観察は正しいです。構文的には、実際に起こることは、関数を呼び出すことだけです。実際、手続き型メカニズム(C++の関数ポインターなど)を使用して、オブジェクト指向言語の多くの機能を実装できます。したがって、オブジェクト指向の設計を行い、それを手続き型言語で実装することができます(たとえば、古いC++コンパイラーが行ったように)。

オブジェクト指向のパラダイムの重要性は、言語メカニズムにおいては、思考と設計のプロセスほど重要ではありません。手続き型プログラミングでは、操作について考え、他の操作を使用してそれらの操作を分解し、それらをモジュールにグループ化するなどです。これは、データまたは状態が2番目の重要性に該当することを意味します。数学的操作を考えるようなものです。

一方、オブジェクト指向のパラダイムでは、状態と操作を1つのエンティティとして考え、プログラムを状態を交換して操作をアクティブにするエンティティ間の相互作用として設計する必要があると述べています。

15
Uri

IMHO、オブジェクト指向プログラミングは、手続き型プログラミングよりも高い抽象レベルで存在する概念です。 OOプログラムの個々のメソッドは、手続き型プログラムの個々の関数とほとんど同じように見えます。これは、たとえば、完全に必要な関数型プログラミングとは対照的です。さらに、OO言語ですべてを静的にすることで手続き的に書くことができます。人間のコンパイラであり、OO多くの関数ポインターと構造体ポインターのキャストを使用したC。

OOは、厳密な定義を持つものというより、設計哲学と世界観に近いものです。継承、ポリモーフィズムなどをコードの構造化の主要なパターンとして使用し、低レベルのトリックに頼らずにこれらを表現可能にする構文を提供する必要があります。データのコレクションの状態に作用するコードは、それ自体が存在するプロシージャではなく、データのプロパティであると考える必要があります。白黒ではありません。コードは、「より多く」または「より少なく」することができますOO継承、ポリモーフィズム、クラス、および構造化の手段としての「データのプロパティとしてのメソッド」の世界観にどれだけ依存しているかによって異なります。コードの説明/理解。

10
dsimcha

OOは主に考え方です。 CでOO=(本当にしたい場合...)をプログラムすることができ、C++/Javaで手続き型コードを完全に持つことができます。つまり、表面、それはまだ手続き型である可能性があります。

OOの背後にある考え方は、状態の抽象化です。「データのグループ化」の観点から「考える」のではなく、「オブジェクト」の観点から「考える」、つまりオブジェクトは「インターフェース」です「データのグループ化とこのデータの操作方法」。

それがだから、それはすべて哲学的に聞こえる。

ここで言うことはたくさんあり、小さなSOポストですべてを言うことはできないので、ここに残しておきます。

[〜#〜]更新[〜#〜]
フラナガンの回答 で述べたように、OO言語はこの抽象化を利用する構成を実装します。

つまり、構造体、関数、関数ポインターの観点から、クラスと多態性を技術的に「ハッキング」することができます。

OO in C の例です。

8
hasen

違いは、オブジェクトのプロシージャと関連データが同じ場所にあることです。プロシージャ言語は、構造体(関連データをまとめて保持するもの)を使用して、データをプロシージャから分離します。事実上、OO言語で行うことはすべて、構造言語と手続きを組み合わせた手続き型言語で可能です。

主な違いは、OO言語がプログラマーを置くマインドセットです。

6
vanja.

[プライマーのスタイルを許してください、それは遅く、私は疲れています]

プロシージャはデータを処理します-データの入力、一部の処理の適用、データの取得

場合によっては、一部のデータ要素が他の一部のデータ要素に関連付けられているため、それらをまとめてデータ構造にグループ化すると、1つの単位として操作およびアドレス指定できるようになります。

これで、プロシージャはデータ構造を入力として取得して変更したり、出力として別のデータ構造を生成したりできます。

一部の手順は特定の種類のデータ構造のみに関係していることに気づく場合があります。これらのプロシージャをデータ構造とともにグループ化し、それをobjectと呼ぶと便利です。

オブジェクトを作成するためのテンプレートはclassと呼ばれます。オブジェクトはクラスのinstanceと呼ばれます

あるクラスは別のクラスに非常に似ていることに気づくかもしれません。そのため、コードをコピーして貼り付ける代わりに、あるクラスにinheritを別のクラスから許可します:subclasssuperclassまたは「基本クラス」。このようにして、サブクラスはスーパークラスのすべてのデータ構造とプロシージャにアクセスでき、特定の方法でそれらを拡張またはオーバーライドできます。

残酷にそのプロシージャを直接呼び出すのではなく、オブジェクトに何かを丁寧に要求する場合、実際の「メッセージ」が送信されない場合でも、これはメッセージパッシングと呼ばれます。ここでの喜びは、多くの異なる種類のオブジェクトが同じメッセージを理解する可能性があることです。これはpolymorphismの概念につながります。たとえば、さまざまな種類のドキュメントに印刷を依頼することができ、それぞれが適切に応答します。

メッセージの受け渡しと継承を備えた(クラスを介するかどうかにかかわらず)オブジェクトをサポートする言語はobject-orientedと呼ばれます。継承がない場合、言語はobject-basedになります。

勉強頑張ってね!

6
Steven A. Lowe

手続き型は、プログラムが何をすべきかを説明するさまざまな方法間の手続き型/関数型/論理(または論理指向)の区別(c、LISP、およびプロローグを比較)の一部です。

オブジェクト指向は、この他のアイデアと直交しており、データを使用してサブプログラムをグループ化する方法を説明します。 C++とJavaはオブジェクト指向機能を備えた手続き型言語です。fortran77はオブジェクト指向機能を備えていない手続き型言語です。一般的なLISPはオブジェクト指向をサポートしています。一部の古いlispsはサポートしていません。プレーンバニラプロローグはオブジェクトをサポートしていません。そして、私は論理指向の言語を指定することはできません(私は論理指向のプログラミングをしていません、それは私が持っているいくつかの豊富な余暇のときにやるべきことの私のリストにあります。私はほとんど機能しませんプログラミング)。

ただし、他の人が指摘したように、適切なオブジェクト指向の考え方は、手続き型から関数型への切り替えと同じくらいプログラミングの方法を変更します。


ところで、私は「手続き型」が非オブジェクト指向の手続き型言語とオブジェクト指向の兄弟を区別するために多く使用されているように見えますが、これは「オブジェクト指向ではない」という明確な形容詞の欠如に起因する不適切な使用法だと思います。 YMMV。

4
dmckee

手続き型プログラムでは、大きな問題を小さな問題に分割し、これらの小さな問題それぞれを手続きとして抽象化します。これは手続き型抽象化と呼ばれます。

オブジェクト指向プログラムでは、問題をいくつかのオブジェクトとして分析し、オブジェクト間の相互作用を分析します。これはオブジェクト抽象化と呼ばれます。

2
wlqSmiling

コンテキストで理解するのは簡単です。言語間に導入された他の抽象化を見てください。

アセンブリ言語とCやPascalなどの手続き型言語の主な違いは、「手続き型」の抽象化の導入です。アセンブリコードを記述している人はプロシージャを作成しますが、その困難でエラーが発生しやすい手続き言語は、それを容易にするツールを提供します。

手続き型言語とOO C++のような言語の違いは、「オブジェクト」の抽象化です。「c」を書く人は、しばしば概念的なオブジェクトを作成します しかし、困難でエラーが発生しやすい =、OO言語は、それを容易にするツールを提供します。

Microsoft(またはErlang)の Sing# のようなものは、メッセージ/プロセスの抽象化を言語に追加します。確かに、メッセージの受け渡しとプロセスの作成はAssembly、C、またはC++で実行できますが、Sing#を使用すると簡単になります。

それはすべて同じマシンコードに帰着します。これらの抽象化は純粋に私たちの頭脳の利益のためであり、コンピュータではありません。

2

違いは

プロシージャ指向プログラミング-データではなくアルゴリズムを重視します。このプログラミング方法は、プロシージャ、つまり特定のタスクを実行してデータ構造を共有する方法に重点を置いています。トップダウン構造に従います。

例:PascalおよびC

オブジェクト指向プログラミング-アルゴリズムよりもデータを重要視します。ボトムアップ構造に従います。すべてのものはオブジェクトとして表示されます。各オブジェクトには、独自のデータ構造と手順があります。データ非表示、ポリモーフィズム、カプセル化、メッセージパッシングなどの機能が含まれています。ユーザーは、プログラムでオブジェクトを使用している間、これらのオブジェクトの内部を気にする必要はありません。

例:C++およびJava

2
myk.

これは簡単な答えです。

  • 真のOO言語では、手続き型コーディングはオブジェクト内でのみ行われます。

  • Cにはオブジェクトがなく、C++はオブジェクトをサポートする言語です。 Java一方、プリミティブを除くすべてがオブジェクトです)すべてが入力されます。

  • 線形進行はオブジェクトの内部で発生しますが、オブジェクト自体はコードとデータのコレクションにすぎません。
1
WolfmanDragon

OOPの定義方法によって異なります。オブジェクトのメソッドを呼び出すJavaのようなOOPに関しては、手続き型プログラミングはほとんど同じです。私が知る限り、すべてをエミュレートできるOOP = Cのような手続き型言語での原則(カプセル化、抽象化、ポリモーフィズム、継承)。この証明は GObject であり、いくつかの拡張Objective-Cであり、他の多くのOOP = cPythonのようなCを使用した言語実装これは、構造体を使用し、関数を使用してそれらの構造体を操作することによって行われます。

typedef struct {
    Object *isa;
    String *name;
    Date *birthday;
} Person;

Person *Person_new();
String *Person_name(Person *self);
void Person_setName(Person *self, String *newName);
// ...

インターフェースは非常にOOPに似ています。これは実際には多態性を許可していませんが、それも可能です。Pythonインターフェースに非常に似ていますが、属性は「メソッド」とは別です。

class Person(object):
    def __init__(self):
        self._name = ""
        self._age = datetime.datetime.now()

    @property
    def name(self):
        return self._name

    @property
    def age(self):
        return self._age

Cの例のように「自己」が明示的であるため、Pythonを例に選択しました。Javaなどの多くのOOP言語は、これを抽象化しています。

Smalltalkに似たOOPの場合、メッセージはオブジェクトのメソッドを呼び出すのではなく、オブジェクトに送信されます。違いは一見すると微妙ですが、多くのパワーと柔軟性を提供します。これはObjective-Cで証明されているように、手続き型言語で実装することもできます。

オブジェクト指向プログラミングは必ずしも言語の一種ではなく、パラダイムです。 Java、Python、Rubyなどのオブジェクト指向言語は、オブジェクトを簡単に操作するための構文糖を提供します。これが「手続き型言語」と「オブジェクト指向言語」の主な違いです。

実際、ライブラリ、または構造体で動作する一連の関数は、C++のオブジェクトと同じです。実際、C++はそのように実装されています。

1
sebnow

すでにここで述べた興味深い点がたくさんあります。

それについて考える1つの方法は、オブジェクト指向では、固有の特性と動作を持つものである「オブジェクト」の概念を持っているということです。それらは通常、それらに関するいくつかの情報を取得するメカニズムを提供するある種の公開「インターフェース」を持っていますが、オブジェクト自体、またはむしろその「クラス」は、公開される情報を制限します。オブジェクトの内部で公開されていないのは、通常、オブジェクトの「内部」にある汚い詳細を知る必要がないためです。そのため、オブジェクト指向プログラムは、この構造およびその他のものを利用します。

手続き型プログラミングでは、通常、このようなデータと動作の結合を「オブジェクト」に利用しません。私は以前Cでそれを行ったのを見たことがありますが、C++で何ができるかを概算するのに、かなり面白くて複雑なモンキービジネスではありませんでした。

オブジェクト指向開発の背後にあるアイデアの1つは、私があなたが提供したもの以外の方法であなたのデータをいじくることはできないはずだということです。十分に検討されたインターフェースのみを提供していただければ、正直に言っていただけます。手続き型のアプローチを使用していて、組み込みの保護機能のない構造を送ってくれたら、私は好きなようにできますし、私が愚かでも悪でも、私が望まないかもしれないことを変えることができます変化する。

確かに、賢い場合はオブジェクトを回避できますが、これを行うには邪魔になりません。

これは完全ではありませんが、1つの側面です。

0
itsmatt

C++の実装方法は、OOプログラミングを手続き型プログラミングによく似たものにするだけです。考え方を少し変える必要があります。

C++では、オブジェクトには、オブジェクトに作用する単なるプロシージャであるメソッドがあります。しかし、実際のOOパラダイムでは、メソッドはオブジェクトが受け取ることができる潜在的なメッセージ(つまり文字)と考える必要があります。オブジェクトはメッセージを受け取ります(パラメータはメッセージのペイロードを表します)手紙の内容)、メッセージに基づいてその状態を変更します。

0
Martin York

手続き型オブジェクト指向とOOの違いのかなりわかりやすい例については、Smalltalkを学習してみてください。 Smalltalkでは、すべて、そして私はすべてがオブジェクトであることを意味します。 ifステートメントやwhileループはありません。その機能を実現するには、他のオブジェクトに(つまり、メソッドを呼び出す)メッセージを送信します。最初は本当に頭が回転しますが、OOが何であるかをすぐに理解できると思います。

0
moffdub