オブジェクト指向と関数型の違いを教えてください。

検索して色々調べてみたのですが「結局どちらもかわらない」との意見が殆どでした。
私もプログラミング効率や保守・管理の手間はどちらも変わらないと思います。

回答の条件
  • 1人2回まで
  • 登録:
  • 終了:2008/11/28 12:03:07
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

ベストアンサー

id:ksh No.4

回答回数315ベストアンサー獲得回数9

ポイント20pt

まず、前提ですが、

・関数型とは Lisp 等の関数言語ではなく、C のようなオブジェクト指向でない言語を示す

ということで書いてみます。

Cで関数を書いてゆくのは、ある意味「プログラム全体を1つのオブジェクトとして記述する」ということになると思います。ですので、規模によってはわざわざクラス設計するより、面倒がなくて良いかもしれません。しかし、それなりのプログラム構成がちゃんと設計できていないと、後々面倒なことになるのは当然のことかと思います。

ではオブジェクト指向技法を用いることだけで変わるか、というとNOと言わざるを得ません。おかしなクラス設計は、生産性を向上させるどころか低下させることも普通にあります。適切なクラス設計を行い、どこでどのレベルの機能を提供するか、それをちゃんと設計できる必要があります。

個人的に、十分に小さいシステムならCでがりがり書いたほうが開発自体は早いと思います。

またシステム規模が大きくなれば、システムを正しく分割し、分割された機能をそれぞれ正しくオブジェクト指向的に抽象化し、良いAPIを提供する設計ができれば、生産性、保守性共に良いものができると思います。

良い設計ができるならオブジェクト指向のほうが良いものができると思いますが、単なる技法の差以外の部分の影響の方が大きいと考えています。

id:koujirou6218

少しスッキリしました。

オブジェクト指向を取り入れるだけでは何もかわらないということですね。

何でもそうですが、使いようが大事ですね。

大規模な開発にはもちろん、適切なシステム細分化と抽象化は大事ですね。

2008/11/28 02:42:41

その他の回答4件)

id:Magical-Soft No.1

回答回数19ベストアンサー獲得回数0

ポイント20pt

オブジェクト型と関数型ですか、私はどちらの手法でも開発してますけれども、個人的にはこう考えてます。

オブジェクト型だと、同じ構造体とそれらを拡張した構造体をもったデータの管理が楽です。

たとえば洋服のデータ管理で、

[服]

+[男性向け]

+[女性向け]

+[子供向け]

みたいにオブジェクトを作るわけですが、たとえば洋服って男女で号数ちがいますよね。オブジェクト型だとその差を吸収できます。

プログラム側では、[服]を管理するだけで、その派生である[男性向け][女性向け][子供向け]を意識する必要がなくなります。

これがオブジェクトでない方法を使うと逆に男性女性子供の違いを考慮した管理関数を用意しなければなりません。

…とこういう回答でよろしかったでしょうか?

id:koujirou6218

確かに、継承が可能なのでその点は便利ですね。

また、ソースコードも短くなるのでよいかもしれません。

しかし継承での最大のデメリットは親を改変した時、継承を使いまくっていると互換性を高める必要がでてくるところでしょうか。

使い分けが重要なのかな?

回答の意図はOKです。ありがとうございます。

質問を補足すると、「オブジェクト指向がいいよ」と言っている人をたまに見かけるので

なぜそこまで「オブジェクト指向」を薦めるのかを疑問に思っていました。

オブジェクト指向、関数型に関して客観的な回答を求めています。

2008/11/27 14:56:20
id:God_24 No.2

回答回数4ベストアンサー獲得回数0

ポイント20pt

「保守・管理」の面で考えると

  • 関数型

main関数に全てのロジックを突っ込むため、ソースコードの規模が大きくなるほど保守が難しいと思います。

  • オブジェクト指向

ロジックを適切なクラスに分けて設計できるため、保守が容易であると思います。しかし、複雑なロジックで継承を利用する場合、継承構造が深くなり、サブクラスから親クラスをコールするような依存循環構造が発生して、手に負えなくなってくることもありますが・・・。


こんなところでしょうか。「プログラミング効率」は扱うシステムによって異なるのではないでしょうか。

id:koujirou6218

なるほど、mainメソッドのことをすっかり忘れていました。

「関数型よりオブジェクト指向の方がいい」という暗黙の了解があるかと思いました。

結局のところ、設計によって異なるということですね。

その、設計にマッチしたプログラミングをするべきなのですね。

当たり前なんですけど、何が最適なのかは難しいところですよね。

まだまだ、回答募集していますよ!!

2008/11/27 18:58:14
id:hijk05 No.3

回答回数1307ベストアンサー獲得回数23

ポイント20pt

あの、回答2を見る限り、C言語みたいなのを関数型言語と言っておられるのかもしれませんが、関数型言語というのは、http://ja.wikipedia.org/wiki/%E9%96%A2%E6%95%B0%E5%9E%8B%E8%A8%8...こういうのです。LISPとかそういう系統の言語です。

C言語みたいなのが関数型だとするなら、関数を集めてオブジェクトとして使えるのがC++であり、オブジェク指向言語です。

>私もプログラミング効率や保守・管理の手間はどちらも変わらないと思います。

オブジェクト指向を有効に使えば違います。オブジェクト指向は、C言語とかの手続き型言語の保守・管理のしにくさを改善するためにできてきたものです。厳密にいうとオブジェクト指向の法が実行速度の面で不利な面があります。

id:koujirou6218

言語ではなく、技法ですね。(プログラミングは技法でいいのかな?)

オブジェクトとして利用できる言語でも、関数にして呼び出しているものとオブジェクトにして呼び出していることに明確な違いがあるのかという疑問でした。

わかりにくくて、すいません。

>>厳密にいうとオブジェクト指向の法が実行速度の面で不利な面があります。

これは知りませんでした。

厳密とおしゃっているので、微々たる差なのでしょうか。

2008/11/27 19:49:23
id:ksh No.4

回答回数315ベストアンサー獲得回数9ここでベストアンサー

ポイント20pt

まず、前提ですが、

・関数型とは Lisp 等の関数言語ではなく、C のようなオブジェクト指向でない言語を示す

ということで書いてみます。

Cで関数を書いてゆくのは、ある意味「プログラム全体を1つのオブジェクトとして記述する」ということになると思います。ですので、規模によってはわざわざクラス設計するより、面倒がなくて良いかもしれません。しかし、それなりのプログラム構成がちゃんと設計できていないと、後々面倒なことになるのは当然のことかと思います。

ではオブジェクト指向技法を用いることだけで変わるか、というとNOと言わざるを得ません。おかしなクラス設計は、生産性を向上させるどころか低下させることも普通にあります。適切なクラス設計を行い、どこでどのレベルの機能を提供するか、それをちゃんと設計できる必要があります。

個人的に、十分に小さいシステムならCでがりがり書いたほうが開発自体は早いと思います。

またシステム規模が大きくなれば、システムを正しく分割し、分割された機能をそれぞれ正しくオブジェクト指向的に抽象化し、良いAPIを提供する設計ができれば、生産性、保守性共に良いものができると思います。

良い設計ができるならオブジェクト指向のほうが良いものができると思いますが、単なる技法の差以外の部分の影響の方が大きいと考えています。

id:koujirou6218

少しスッキリしました。

オブジェクト指向を取り入れるだけでは何もかわらないということですね。

何でもそうですが、使いようが大事ですね。

大規模な開発にはもちろん、適切なシステム細分化と抽象化は大事ですね。

2008/11/28 02:42:41
id:rso No.5

回答回数5ベストアンサー獲得回数0

ポイント20pt

もう既に何人の方が指摘されているようですが、Cなどのプログラミング言語を

関数型と呼ぶには語弊があります。

これらは手続き型言語と呼ばれています.

参考:http://e-words.jp/w/E6898BE7B69AE3818DE59E8BE8A880E8AA9E.html

関数型言語はLisp,Haskellなどのプログラミング言語を指し,

手続き型言語,オブジェクト指向言語とは非なるものです.

また,手続き型言語に比べてオブジェクト指向言語の利点としては,再利用性の向上が上げられます.

例えば,オブジェクト指向で設計されたあるフレームワークやライブラリを,

一部修正・機能追加して利用したいとします.

この場合,既存のクラスを継承して,自分の追加・変更したい機能だけを書くことで

利用することができ,既存のクラスに自分の修正の影響を与えません.

(手続き型言語では,既存のコードを書き換えるか,コピーをそのまま持ってきて書き換えるしか

無いでしょう)

あくまでオブジェクト指向設計がうまく行われていた場合の話なのですが,

何でもオブジェクト指向設計でプログラムを組めば良いというものでもありません.

ただ,うまくオブジェクト指向設計されていれば,再利用性,保守性と言う点では

有利ではあると思います.

  • id:ku__ra__ge
    サブルーチンや関数を使えばプログラムの「部品」を共通化できまが、オブジェクト指向を使えば「部品を組み込む枠」を共通化できます。

    10種類のカンマ区切りテキストファイル(CSV)を出力するプログラムを作る、という例を考えると分かりやすいと思います。
    1つ1つのCSV出力は、ファイルを開いてタイトル行を書き出し、データを取得し、ループしてデータを書き出すという手順で行われます。サブルーチンや関数を駆使して10種類のCSV出力処理を記述すると、各種類のCSVを出力するためには、この手順を10個分書くか、ファイルを開くなどの共通化できる手順を10回分ループしてタイトル行出力部分などをCSV種類ごとにswitchやif文で10分岐させる、というコードを書かなければなりません。
    しかしオブジェクト指向ではCSV出力のBaseクラスを作成してそこに、ファイルを開いて[タイトル行を書き出し]、[データを取得]し、ループして[データを書き出す]という、CSV出力の枠となる手順を記述することで、枠となる手順を1個所にまとめることができます。(カギ括弧で囲んだ部分は各CSVごとに異なる処理が必要な個所。実際のコードではオーバーライド可能なメソッドとして記述します)
    そのクラスを継承して各種類のCSVを出力するクラスを作成し、子クラス側ではCSVごとに異なる処理だけを記述すれば、CSV出力の共通手順を何度も書いたりswitchやifで不自然に処理を分岐させることなく10種類のCSV出力を行うコードを書くことができます。
    このようにオブジェクト指向では、ある場所だけ各種類ごとに別の処理をして残りは同じ処理をしたい、というときに枠となる処理を1箇所にまとめるて共通化することができるのです。

    上記のようなことは、関数をまるごと引数に渡せばサブルーチンや関数を使っても似たことができるのでは……と思われるかもしれません。しかし、各種類ごとに処理を変える必要がある場所が1,2箇所ではなく10個所以上もある場合はどうでしょう。やはり関数ポインタを引数に渡す方法だけでは無理が出てきます。
    (それでも関数を引数に渡すという方法は、各種類ごとに処理を変える必要がある場所が1,2個所の場合には有効な方法で、実際にいろんな言語で活用されている方法ではあります。)

    ちなみにクラスには他にも、変数や関数が見える範囲(スコープ)を制限してプログラマが把握しなくてはならない情報量を押さえるという効果もあります。この特徴も非常に重要ではありますが、これはC言語(not c++)のstatic, externでも出来ることなのでオブジェクト指向特有の特徴というわけではないと思います。

    そして最後に、忘れてはならないことを1つ。
    オブジェクト指向でコードを書くと、どうしても1つの処理が複数の場所に分散して、処理の内容を把握するためにプログラマが確認しなければならない範囲が増えます。そしてこれはプログラムの可読性を落とすマイナスの特徴です。
    つまり、オブジェクト指向で書くと必ずある程度は可読性が落ちてしまうのです。ですから、オブジェクト指向で書くこと得られる可読性の向上やコードの拡張性が高くなるというメリットが、このデメリットを上回らない場合は、オブジェクト指向で書くとコードは無駄に読みにくくなってしまいます。
    (オブジェクト指向の入門書などで載っているサンプルコードは、大抵はこの「オブジェクト指向で書くとコードが読みにくくなる」例になってしまっています。紙面の関係や理解しやすいコード量を考えると仕方ないのですが)
    ありがちな例ですが、オブジェクト指向は薬に例えられます。正しく使えばプラスの効果をもたらしてくれますが、間違った使い方をすればそれは薬ではなく毒になってしまいます。
    用法、用量を守って正しく使いましょう。

    # 後で書こう、と思っていたら回答の投稿に乗り遅れましたw
    # 構造化プログラムはオブジェクト指向プログラムと違い、とにかく使えばプログラムが
    # 分かりやすくなるという面があるので、そうではないオブジェクト指向は
    # 理解され辛いかと思います。

この質問への反応(ブックマークコメント)

トラックバック

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません