この記事はオブジェクト指向でなぜつくるのかをまとめたものです。
3章から4章までのプログラミングに関する内容だけまとめています。
オブジェクト指向が主流になる以前
プログラミングの歴史は人間がどれだけ読みやすく、書きやすいプログラムを作れるかという目的のもと人間が努力し、考え続けていることである。
オブジェクト指向もその目的のために生まれ、採用された方法である。
以下ではオブジェクト指向が主流になる前の歴史と問題点をまとめていく。
プログラミング言語の進化
元々は一部のスーパープログラマーが機械語そのものを解読し、一つ一つプログラムしていた。
それを人間が読みやすく書きやすくしたものがアセンブリ言語であり、今私たちが利用しているRubyやJavaなどの高級言語なのである。
機械語 → アセンブリ言語 → 高級言語
しかし、それでもコンピュータの普及と発展が爆発的に進んだため、生産性向上のニーズは収まらなかった。
1960年代後半にはNATOの国際会議で20世紀末には世界の総人口がプログラマーになっても増大するソフトウェアの需要に追いつかないというソフトウェア宣言が宣言される事態にまでなってしまう。
主流になる構造化プログラミング
そんな中、注目を集めたのが「正しく動作するプログラムを作成するためにはわかりやすい構造にすることが重要である」という理論である構造化プログラミング。
具体的な方法としてGOTO文の廃止し、順次進行、条件分岐、繰り返しの3つの構造だけで表現することを提唱した。
もう一つ工夫されたことがサブルーチン(関数やプロシージャとも呼ばれる)の独立性を高めることだった。
以前まではグローバル変数が利用されたが、プログラムのどこからでも使われる可能性があるため、変更が難しくなる問題があった。
その問題と前述のサブルーチンの独立性を高めるためにローカル変数と引数の引き渡しが考案された。
さらにこの理論が浸透する中でC言語を代表とする構造化言語と呼ばれるものが登場することになる。
構造化言語ではif文やcase文、for文などで明確に制御構造を記述できるようになった。
残された課題
それでも未だに残るのがグローバル変数問題と貧弱な再利用という課題。
ローカル変数や引数が導入され、情報の受け渡しは必要最小限に抑えることが可能になったものの、ローカル変数はサブルーチン呼び出しが終わると消えてしまう。
そのためサブルーチンの実行期間を超えて保持する必要のある情報はグローバル変数として保持せざるを得なかった。
さらに構造化ブログラミングで再利用できたのはサブルーチンだけだった。
こうした課題を解決していくのがオブジェクト指向プログラミングである。
オブジェクト指向の3つの仕組み
オブジェクト指向は主にクラス、ポリモーフィズム、継承の3つの仕組みによって成り立っている。
以下ではそれぞれの具体的な仕組みを説明する。
3つの仕組みを持つクラス
-
サブルーチンと変数をまとめる
クラスにまとめることによってまず部品が減り、名前づけが楽になり、サブルーチンを探しやすくなる。 -
クラスの内部だけで使う変数やサブルーチンを隠す
クラスに定義した変数とサブルーチンを他のクラスから隠すことができる。これによって保守性悪化の原因のグローバル変数を使わずにすむ。 -
1つのクラスからインスタンスをたくさん作る
一旦クラスを定義すると、実行時にいくつでもインスタンスを作ることができる。これによってファイル、文字列など同種の情報を同時に扱う処理であってもクラス内のロジックをシンプルにできる。
さらにはオブジェクト指向ではクラスを型として定義することができ、そのクラス以外のインスタンスを格納しようとするとエラーとなる。機械語やアセンブリ言語の時代には型チェックは存在しなかった。
高級言語の登場で初めてデータ型などをチェックする仕組みが導入され、オブジェクト指向ではさらに変数とメソッドをまとめたクラスを型として定義することでプログラム内のルールとして強制する仕組みが備わった。
共通メインルーチンを作るためのポリモーフィズム
共通サブルーチンは呼び出される側のロジックを1つにまとめるが、ポリモーフィズムは反対に、呼び出す側のロジックを一本化する。
オブジェクト指向が登場するまでは共通サブルーチンはあったものの、共通メインルーチンはなかった。
フレームワークやライブラリのような大規模な再利用部品もこのポリモーフィズムによって可能になった。
クラスの重複を排除する継承
継承は一言で表現すると「共通部分を別クラスにまとめる仕組み」と言われている。
また、似たもの同士のクラスの共通点と相違点を整理する仕組みであり、全体集合と部分集合に相当すると説明されている。
つまり、ポリモーフィズムで呼び出す側を一本化するだけでなく、継承によって似たようなクラスの共通部分もまとめてしまうという機能。
オブジェクト指向ではその共通クラスのことをスーパークラスと呼び、それを利用するクラスをサブクラスと呼ぶ。
さらに進化したオブジェクト指向の仕組み
パッケージ
クラスをさらにまとめる仕組み。
パッケージはただの容れ物であり、クラスと違い、メソッドやインスタンス変数を定義することはできないが、これが存在することによって、階層構造を作ることができるようになり、クラスの名前の重複を全世界で避ける重要な役割がある。
例外
これは「戻り値とは違う形式で、メソッドから特別なエラーを返す仕組み」と説明されている。
例外によって特別なエラーを返す可能性があるものを全て一括して同じ処理へ流すことができる。
これによってわざわざ可能性のあるエラー一つ一つの処理を書かずに済むようになった。
ガベージコレクション
インスタンスを作成するとインスタンス変数のためのメモリ領域が確保される。
オブジェクト指向のアプリケーションが動作するときにはクラスからインスタンスが大量に作られることがある。
C言語などでは不要になったメモリ領域を削除する処理はアプリケーション内で指示する必要があり、別の場所のインスタンスを誤って削除してしまうという危険や逆に削除を忘れると不要なインスタンスがメモリを圧迫してしまう危険があった。
Javaなどの多くのオブジェクト指向プログラミング言語ではこうしたインスタンスを自動的に処理してくれるガベージコレクションを採用している。
まとめ
機械語 → アセンブリ言語 → 高級言語
から構造化言語。
そして本書のテーマであるオブジェクト指向言語へと移り変わり、そのオブジェクト指向自身も進化している。
まとめる、隠す、たくさん作るという仕組みを持つクラス。
共通メインルーチンを作るためのポリモーフィズム。
クラスの重複を排除する継承。
さらにはクラスをまとめるパッケージ。エラー処理を簡単にする例外。不要なインスタンスを自動で削除してくれるガベージコレクション。
最後にオブジェクト指向プログラミングで作る理由としてプログラムの品質や保守性、そして再利用の向上を目指し、無駄を省いて整理整頓をするための仕組みである。
と言っていました。