1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

オブジェクト指向と関数型プログラミングは適材適所であるとか、良いとこ取りをすればいいという意見をそこらで見かけるのですが、はっきりいって両者には対立構造があり排他的存在なのでは?

Last updated at Posted at 2025-09-11

誤解があるようですが、「関数型プログラミング」が対立する相手は「手続型プログラミング」です。決してオブジェクト指向ではありません。

すぅ…(息を吸う)

もう一度言います。「関数型プログラミング」が対立する相手は「手続型プログラミング」です。オブジェクト指向とは対立していません。

質問そのものに大きな誤解があるのに誰も突っ込まないので、遅ればせながら回答追加します。

main-qimg-b8ec3c4331b1be56389e55dfe0cd6fd1.jpg
「どっちがスゴいか勝負!」 (Bing Image Creatorで生成)

数学的アプローチから発展した 関数型プログラミングには「関数は他の関数に干渉しない」というシンプルなルールがあります

これは数式と同様、どれだけ処理を分散しても出力される結果が変わらないことを意味するため、数十年前には将来実現するであろうペタバイト級の処理を行う大規模分散システムでは関数型プログラミング言語が一世を風靡するに違いないと期待されました。

とはいえ「純粋な」関数型プログラミングには、「結果をハードウェア(ディスプレイ含む)に出力する」とか「各関数の処理結果を一つに取りまとめる」方法がありません(共有資源にアクセスすると関数間の干渉が起きるため)。さらに1つの関数内に記述できる量にも限界があります。つまり「純粋な関数型言語」で現代的なプログラムはまともに書けない のです。

それで、関数型プログラミング言語にもいろいろな「手続型関数」が用意されていて、それを呼べば必要な処理が可能になっています。つまり 関数型プログラミング言語は最初から色々と妥協しています。「純粋な関数型言語は存在しない」と指摘する方々がいらっしゃるのはこのためです。

とはいえ、英語などの自然言語から発展した 手続型プログラミング言語にも、「ある手続き(処理)が終わるまで次の手続きに進めない」という構造上の欠点があり、これを「チューリング完全」と言います

チューリング完全とは、プログラムコードを1本道のようにひたすら読みつつその通り処理していくというシンプルな概念です。昔はこれでうまくいっていたのですが、これだと処理が終わってコンピューターが「次は何をしますか?」と聞いてくるまでマウスもキーボードも反応しません。困りますよね。それで、手続型プログラミング言語も「スレッド」とか「イベントループ」などの手法で擬似的にリアルタイムの反応が可能なプログラムに見せかけています。

まぁ、そもそもコードがただの1本道なら関数型言語由来の「関数」で処理を分割する必要もないはずですが、今どきそんな単純なプログラムはありません。それで、手続型プログラミング言語も今では色々と妥協しています。現代において「純粋な手続型プログラミング言語」も存在しないのです。

結果、「純粋な関数型」プログラミングも「純粋な手続型」プログラミングも、どちらも厳密には敗北しています。これは 単純な話、関数型と手続き型どちらの性質も必要 だからです。今どきのほとんどの人気言語は両方のパラダイムを利用できる機能や構文を提供しています。それぞれの状況に合わせて好きに混ぜて書いてくださいって感じですね。

上記、最初は対立(?)していたものの、後に仲良く混ざり合った2つのパラダイムに対し、「オブジェクト指向」という概念は、プログラムが時代と共に巨大化していく中で生まれた単なる「構造化技法」の1つ に過ぎません。どんなプログラムも複雑になればなるほど、「プログラムコードを見通しよく管理する」必要が大きくなります。数千行のプログラムがそのままべたっと書かれていたら読む側は卒倒しますよね。それは関数型でも手続き型でも同じことです。

ですからCやLuaなどシンプルな言語はファイル単位、他の多くの言語は「オブジェクト」という単位でプログラムをまとめて管理し、関数よりもう少し大きなまとまりでプログラムを「部品」として再利用しやすくする「構造化プログラミング」の一つの完成形が、現代の「(一般的な)オブジェクト指向プログラミング」 です。

それで「何をもってオブジェクト指向とみなすか」は、言語によって異なります。片付けの方法が人それぞれ違うのと同じく、プログラムコードを整理する方法も言語ごとに違います。むしろこれは言語設計そのものなので、各言語ごとに好きに定義したらいいと思いますしそうなってます。

例えばC++やPHPはフル機能のオブジェクト指向言語ですが、オブジェクト指向を使いたくなければ全く使わなくていいようになってます。Javaは少し厳しくて、main関数含め全てのデータも関数も必ず何らかのオブジェクトに属しています。Rustは構造体と属性(関数のまとまり)をそれぞれ宣言してから結合する少々珍しい手順が要求されます。Pythonはぱっと見オブジェクト指向を使わずに書けるものの、実は全てのコードがオブジェクト指向な言語です。でも こういう部分は言語設計の話で、オブジェクト指向そのものの定義とは全く関係ありません。記法や文法が違うだけの話 です。

なお、特定の言語に依存しない「オブジェクト指向」そのものの概念を学びたければ、オブジェクト指向の父アラン・ケイ氏の発言を横断的に分析してみることをお勧めします。アラン氏は完全オブジェクト指向の言語として有名なJavaにはひどく否定的で、かなりボロクソにこき下ろしています。彼はプログラム言語Smalltalkの設計者でもありますが、Smalltalkは現代の「一般的なオブジェクト指向」とはかなりかけ離れた概念を持っています。ちなみにMacやiOSで使用されるObjective-CやSwiftなどはSmalltalkの影響が強い言語ですよ。とはいえSmalltalk自体、バージョンを経るごとにじわじわと一般的なオブジェクト指向言語に近づいている気もするのであくまで参考程度にどうぞ。まぁ好みや定義の派閥争いは脇に置いて、どの理論も原典を調べてみるのは大事ですね。

個人的に アラン氏の語る(思想としての)オブジェクト指向は、現代ではコンピュータ言語よりサーバークラスターの分野で実現に近づいている気がします。下の回答で触れてますのでご参考にどうぞ。

もう一つ、少し大きな視点で言えば、データベースそのものもある意味で「オブジェクト」 です。データベースも中身はプログラムですから、関数型言語では「状態」はなるべくデータベースに格納し、関数ごとに必要なだけ取得する仕組みにすると良いでしょう。ちなみに 最近のWebフレームワークの多くは、URLやイベントに対応する関数が独立していて、かなり関数型言語寄りの構造をしています。でも中身は完全なオブジェクト指向です。オブジェクト指向と関数型プログラミングの2つのパラダイムがうまく共存する好例ですね。

なんにせよ、オブジェクト指向はあくまでただの「構造化プログラム技法」の1つで、どんな言語でも好きにとらえて使えばいいと思います。使ったところでコンパイルエラーが出ない限りは誰も怒りませんよ。

…てか長いな!

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?