連載:[完全版]究極のC#プログラミング

Chapter1 C# 3.0らしいプログラミングとは?

川俣 晶
2009/07/31

1.7 クラスベースの問題点

 クラスベースとプロトタイプベースは互いにどのような位置付けにあるのだろうか?

 筆者も不勉強で知らなかったのだが、実はプロトタイプベースとは、クラスベースの問題を解決するために提唱された、より新しい概念ということらしい。プロトタイプベースの最初の言語はSmalltalkを改良した「Self」という言語であり、1986年にはすでに設計されていたらしい。

 つまり、PC上のOOPのブームが始まってすらいない1980年代のうちに、すでにクラスベースの問題点は指摘されていたのである。

 さて、クラスベースの問題とは何だろうか?

 それは、変化に弱いことと例外的な処理に弱いことだと、筆者は考える。

 変化に弱い……というのは、奇異に思えるかもしれない。なぜかといえば、クラスには継承という強力な機能があり、元のクラスを書き換えることなく異なる振る舞いを持つオブジェクトを作り出すことができるからである。

 ところが、このような強力なカスタマイズ能力を発揮できるのは、元クラスの定義に変化が必要とされない場合に限られる。もし、多数のクラスの基底クラスとなったクラスに修正が必要となった場合、その変更の影響は多数のクラスに及び、とても簡単には済まない。かといって、あらゆる拡張に対応できるような万能のクラス定義を目指すと、あらゆる可能性に対する無限の備えを行うことになり、現実的なシステムとしては破綻してしまう。

 実は、クラスベースのOOPは、クラス数がある程度増えると、そこで1つの壁に突き当たるのではないか……という印象もある。その壁に達すると、うかつにクラスの定義を書き換えられなくなり、どうしてもコーディングの手が止まってしまうのである(実は、筆者がC# 1.xで書いていたメーリングリストサーバーの「りすと亭」の開発が滞っている理由はこのあたりにあるような気がする)。

 例外的な処理に弱い……というのは、特定の条件を満たす場合にのみ別の処理を行う、といった処理を扱いにくいという意味である。「例外的な処理」の具体的な説明は、過去に筆者が書いた記事(http://www.atmarkit.co.jp/fdb/rensai/xmldbdev01/xmldbdev01_2.html)にあるので、以下に引用しよう。


XMLデータベース開発方法論(1)
序章 データ処理技法の地政学 Page 2/4
例外的処理こそが重要である

 1980年代、筆者は「ドラクエ」で有名なエニックス(現スクウェア・エニックス)でプログラミングの仕事をしていた。そのころ、エニックスには、マニア上がりのすご腕のプログラマが何人もいて、技術を競っていた。また、パソコンのスペックが貧弱であるために、職人芸的なすご腕がなければ成立しないソフトも多かった時代である。このような時代、彼らと話していて必ず同意する話題があった。それは「例外的処理が重要」という考えであった。ここでいう「例外的処理」とは、最近のプログラム言語が備える「(try構文などで使用される)例外」のことではなく、基本的なルールから外れた特殊な処理のことをいう。

 例えばゲームの例でいえば、シナリオの都合上、通常の処理とは異なる例外的な処理がしばしば要求される。弾が当たればダメージを受けるというのが通常の処理だとすれば、シナリオ上勝てないとされた強敵と遭遇した場合だけは弾が当たってもダメージを受けないようにするのが例外的な処理に当たる。通常の処理を短くエレガントに記述するのは容易なのだが、例外的な処理はまさに例外的であるために、短くエレガントにまとめられないことが多い。しかし、だからといって長々と泥臭いコードを書いていては、貧弱なスペックの当時のマシンでは実行できなくなってしまう。つまり、「例外的処理が重要」ということになるわけである。


 ここでいうような例外処理に、クラスベースはとても弱い。クラスを設計した時点では予測もしなかった例外処理が要求されたとき、玉突き的に多数のクラスに変更が求められることもありうる。それだけではなく、あくまで局所的、例外的な処理にすぎないにもかかわらず、クラスの全体的な設計の整合性を配慮すると、多くのクラスが参照する基底クラスのレベルで配慮しなければならないこともある。

 これらの問題に対処するために生まれたのがクラスのないプロトタイプベースであるが、実際の世の中は、すべてをクラスで解決するというJavaに向かって急速に流れていった感がある。実はJavaと並行してJavaScriptという優秀なプロトタイプベースのOOP言語が存在していたにもかかわらず、それがOOP言語であるという事実すら浸透しなかった。クラスベースの問題に対する批判は黙殺され、世間に幅広く知られることはなかったのである。

 そのような観点からC# 1.xを見ると、実は興味深いことがわかる。クラスですべてを解決するというJavaと異なり、C# 1.xとはデリゲート型などの新しい仕掛けを導入することによって、クラスを絶対的な地位から引き下ろしたOOP言語であると見ることができるのである。それこそが、Javaと比べたときのC# 1.xの圧倒的な実用性の高さの源泉といえるかもしれない。しかし、C# 1.xはクラスに対する依存性がまだ強かった。そして、C# 3.0になって、ついにクラスを主役の座から引き下ろした、といえるかもしれない。つまり、C#の進化の歴史とは、問題の多いクラスからの決別の歴史であると見るとよいのかもしれない。

【C#olumn】クラスの問題とは何か?

 あくまで筆者の個人的な感想でしかないが、クラスベースという方法論ではなく、具体的な言語の機能としてのクラスの問題とは以下の2点に集約されると感じる。

  • 機能が過剰に強力である
  • 多重継承の禁止によって本来の機能がうまく発揮できない

 第1の理由により、クラスだけでたいていのプログラムは記述可能であるが、パワフル過ぎてプログラマーのほうが振り回されがちだ、と感じる。ラムダ式程度で短く記述すれば済む機能であっても、いちいちクラスを持ち出すのは手間ばかりかかってメリットが少ない。それどころか、過剰な機能性が無用のトラブルを招きかねないリスクも背負い込む。しかし、本当にそれだけの機能性が要求される用途であれば、無理にラムダ式で解決しようとするよりも、クラスを用いたほうがよい。

 第2の理由は、話が長くなるので詳細は略するが、決定的な矛盾が存在すると考える。その矛盾とは、多重継承は多くの問題を引き起こすので禁止が妥当であるが、それでも多重継承抜きではうまく扱えない問題が存在することである。この件については筆者よりも具体的に詳しくこの問題を扱っているOOPの専門家も多いと思うので、彼らに教えを請うとよいだろう。


 INDEX
  [完全版]究極のC#プログラミング
  Chapter1 C# 3.0らしいプログラミングとは?
    1.はじめに/本書の位置づけ
    2.1.1 意外性あり? 本書で解説すること/C# 3.0の適用範囲/筆者の来歴
    3.1.2 C# 3.0らしいソースコードとは?
    4.1.3 コードの遅延実行という例
    5.1.4 インターフェースとの比較
    6.1.5 後退するクラスの立場
    7.1.6 クラスベースとプロトタイプベース
  8.1.7 クラスベースの問題点/【C#olumn】クラスの問題とは何か?
    9.1.8 JavaScriptとの相違点
    10.まとめ/【C#olumn】金のハンマーと銀の弾丸―クラス至上主義
 
インデックス・ページヘ  「[完全版]究極のC#プログラミング」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間