MJHD

エモさ駆動開発

オブジェクト指向とは

新人プログラマに知っておいてもらいたい人類がオブジェクト指向を手に入れるまでの軌跡 - Qiitaなどを参考にまとめたメモ。

オブジェクト指向プログラミングとは,オブジェクト同士の相互作用として,システムの振る舞いを捉える考え方である.所謂手続き型の言語しかなかった時代,コンピュータの性能向上につれて,データ構造,処理の複雑化し,正しく動く可読性の高いプログラムの記述が困難になった.1960年代にはこうした状況に「ソフトウェア危機」[1]という名前が付けられ,新たなプログラミングの手法が模索された.こうして考案されたのが「構造化プログラミング」[2]などのデザインパターンである.構造化プログラミングでは,言語特有のステートメントを直接使うのではなく,抽象化したステートメントを持つ仮想機械を想定し,その仮想機械上でプログラミングを行う.こうすることで, プログラムの正当性や可読性を向上することができるようになる.またこれとともに,「モジュラプログラミング」[3]と呼ばれる,同じ機能を持つ処理同士をモジュールという単位でまとめ,分割する手法が広まっていき,また良い分割を行うために,「状態」と「副作用」[4]を如何に扱うかが問題になっていった.その一つの解決策として現れたのが,オブジェクト指向プログラミングと,関数型プログラミングである.関数型プログラミングでは,基本的に副作用を持たず引数と返り値のみでプログラムを構成することで,参照透過性を保っているが,オブジェクト指向プログラミングでは,状態と副作用を「オブジェクト」に閉じ込めることで,抽象化を行った.このオブジェクト指向言語として初めて現れたのが,Simula[5]である.Simulaには,オブジェクト,クラス,動的ディスパッチ,継承,ガベージコレクションなどの現在のオブジェクト指向言語が持つ機能が実装されていて,後にC言語にこの機能が取り入れられ,C++言語ができた.また, Smalltalk[6]もSimulaに影響を受けた言語として制作され,C言語Smalltalkの機能を取り入れた言語として,Objective-C[7]言語などが作られた. オブジェクト指向プログラミングでは,プログラムはオブジェクトの集合として定義され,特徴として「カプセル化」[8]や「ポリモーフィズム」[9],「継承」[10]などの概念が挙げられる.初めに,カプセル化とは,Simulaで考案されたもので,データと処理を1つのオブジェクトとしてまとめることで,オブジェクト外部への副作用を減らすことができ,プログラムの正当性を高めることができるものである.例えば,グローバル変数を使い状態を共有しているモジュールがあった場合,片方の仕様を変更したとき,もう一方も修正しなくてはならなくなる.このような時,カプセル化を行うことでこのモジュール間の結合をなくすことができる.次に,ポリモーフィズムとは,現在の言語ではオーバーロードや仮想関数,インターフェースと呼ばれる機能などで実現されていて,異なるクラスであっても同一のコードで扱えるよう,クラスが複数のクラスに属すことのできる性質のことを言う.例えば,以下のリスト7の様な処理があった時,printNumber, printDate関数は,以下のリスト8の様に一つの関数としてまとめることができるようになる.最後に,継承とは,あるクラスを基に,機能を追加したり変更したりした別のクラスを定義することのできる機能である.これにより,副作用を基のクラスに隠蔽したまま,新たな機能を追加することができるため,プログラムの正当性,可読性に役立つ.

リスト7. ポリモーフィズムの例1 (疑似コード)


1:  class Number {
2:      public string ToString() {
3:          retutn 文字列へ変換する処理;
4:      }
5:  }
6:  
7:  class Date {
8:      public string ToString() {
9:          return 文字列へ変換する処理;
10:     }
11: }
12: 
13: public void printNumber(Number value) {
14:     print(value.ToString());
15: }
16: public void printDate(Date value) {
17:     print(value.ToString());
18: }
19: // プログラムの開始地点
20: public void main() {
21:     var number = new Number();
22:     var date   = new Date();
23: 
24:     // それぞれ別の関数に渡さなければいけない
25:     printNumber(number);
26:     printDate(date);
27: }

リスト8. ポリモーフィズムの例2 (疑似コード)


1:  interface IConvertible {
2:      public string ToString();
3:  }
4:  
5:  class Number : IConvertible {
6:      public string ToString() {
7:          retutn 文字列へ変換する処理;
8:      }
9:  }
10: 
11: class Date   : IConvertible {
12:     public string ToString() {
13:         return 文字列へ変換する処理;
14:     }
15: }
16: 
17: public void print(IConvertible value) {
18:     print(value.ToString());
19: }
20: // プログラムの開始地点
21: public void main() {
22:     var number = new Number();
23:     var date   = new Date();
24: 
25:     // 同じ関数に異なる型を渡すことができる
26:     print(number);
27:     print(date);
28: }

参考:

[1] ソフトウェア危機Wikipedia, http://ja.wikipedia.org/wiki/%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E5%8D%B1%E6%A9%9F [2] 構造化プログラミング Wikipedia, http://ja.wikipedia.org/wiki/%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E5%8D%B1%E6%A9%9F [3] モジュール Wikipedia, http://ja.wikipedia.org/wiki/%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB [4] 副作用(プログラム) Wikipedia, http://ja.wikipedia.org/wiki/%E5%89%AF%E4%BD%9C%E7%94%A8%28%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%29 [5] Simula Wikipedia, http://ja.wikipedia.org/wiki/Simula [6] Smalltalk Wikipedia, http://ja.wikipedia.org/wiki/Smalltalk [7] Objective-C Wikipedia, http://ja.wikipedia.org/wiki/Objective-C [8] カプセル化 Wikipedia, http://ja.wikipedia.org/wiki/%E3%82%AB%E3%83%97%E3%82%BB%E3%83%AB%E5%8C%96 [9] ポリモーフィズム Wikipedia, http://ja.wikipedia.org/wiki/%E3%83%9D%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%95%E3%82%A3%E3%82%BA%E3%83%A0 [10] 継承 Wikipedia, http://ja.wikipedia.org/wiki/%E7%B6%99%E6%89%BF%28%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%29