オブジェクトは物、対象、目標物と訳される。物や対象そのものに重点をおくプログラミングととらえられているが、その解釈には人によって異なる。ここでは、オブジェクト指向プログラミングのとらえ方を7つ挙げ、その全体像を把握する。
オブジェクト指向プログラミングとは
オブジェクト指向プログラミングと(Object Oriented Programming:OOP)は、プログラム開発手法の一つである。大規模なプログラムの開発を効率化し、保守を容易にすることを目的としている。そのため、マネージャー層には人気があるものの、開発の現場では敬遠されがちである。その大きな原因として学習量がかなり負担となることが言われている。しかし、現状の開発環境はJavaなどが基本となっており、実践の必要が出てきている。
OOPに対する様々なとらえ方
オブジェクト指向プログラミングは、用語辞典などでは以下のように説明されることが多い。
対象(オブジェクト)そのものに重点をおき、対象の振る舞いや操作が、対象の属性として備わるという考え方に基づいてプログラミングすること。プログラムの再利用が容易になり、ソフトウェアの生産性を高められる。主なプログラミング・テクニックには、継承、カプセル化、多態性の3つがある。
用語の説明としてはこれで十分であるが、これで理解するのは難しいだろう。理解するためには自分なりのオブジェクト指向プログラミング像を確立する必要がある。以下に様々なとらえ方を挙げていき、全体像としての理解を深める。
1 部品を組み合わせてプログラムを構築すること
オブジェクト指向プログラミングでは、複数の「クラス」を組み合わせて1つのプログラムを構築する。クラス(部品)とは、関係のある関数と変数をまとめたグループのことである。オブジェクト指向言語(オブジェクト指向プログラミングのための言語)でないC言語やBASICでプログラミングする場合は、命令を「関数」で表し、データを「変数」で表している。しかし、大規模なプログラムでは、プログラムに必要とされる関数と変数の数が膨大なものとなるため、これらをまとめて取り扱うことにしたのである。
C++、Java、C#などのオブジェクト指向言語には,言語構文としてクラスを定義する機能がある。クラスには、MyClassのような名前をつける。クラスにまとめられた関数と変数を「メンバー」と総称する。
C言語にオブジェクト指向プログラミングのための言語構文を追加する形でC++が開発された。C++を改良する形でJavaとC#が開発された。
2 開発効率と保守性を向上するもの
オブジェクト指向プログラミングでは「クラスライブラリ」を使うことで開発効率が上がり、機能修正や機能拡張などの保守性も向上する。クラスライブラリとはクラス群のことで、様々なプログラムから利用できる数多くのクラスが添付されている。他のプログラムのために作った既存のクラスを再利用することで、大きく効率が上げることができるのである。
保守性が向上するのは、保守の対象となる関数と変数がクラスというグループにまとめられているからだ。例えば給与の計算ルールの変更に伴いプログラムを修正する場合、手直しする必要のある関数と変数はKeisanClassのような名前のクラスにまとめられているだろう。そのため、すべてのクラスを見直す必要はなく、KeisanClassだけを修正すればよい(後で詳述)。
オブジェクト指向プログラミングを実践するには「私はクラスを作る人、あなたはクラスを使う人」という感覚が必要になる。開発チーム全員がプログラムの隅から隅までを把握する必要はない。一部の部品を外注することもできる。ただし、クラスを作る側になったプログラマは、プログラムの開発効率と保守性を考慮して何をクラスにすればよいかを決める必要がある。たとえ壊れても(バグがあっても)容易に交換可能な部品としなければならない。
また、機能アップした新しい部品と交換できるようにしておく必要もある。そのためには、クラスの仕様を取り決めておけばよい。クラスという部品を使う人にとって、クラスがどのように見えるかという仕様のことを「インタフェース」と呼ぶ。オブジェクト指向言語には、インタフェースを定義するための構文が用意されている。
3 大規模なプログラムに適した開発手法
これまで説明してきたように、オブジェクト指向プログラミングは大規模なプログラムの作成に適している。10000個の関数と20000個の変数を必要とするプログラムを100個のクラスでグループ化したら、クラス1個あたりの関数は100個程度で変数は200個程度となる。
コンピュータを取り巻く技術は、コンピュータを人間に近づけ、より使いやすいものとするために進歩している。人間の感覚では、大きな物は部品を組み合わせて作成される。それと同じことをコンピュータで行うオブジェクト指向プログラミングは、人間らしく進歩した開発手法だといえる。
4 現実世界のモデリングを行うこと
オブジェクト指向プログラミングでは、プログラムに置き換える現実世界を「モデリング」して分析する。モデリングとは、開発者にとって現実世界がどのように見えるかという世界観を表すものである。
実際のモデリングの作業では、「部品化」と「省略化」を行うことになる。部品化とは、現実世界を複数のオブジェクトの集合体として分割することである。現実世界を100%プログラムに置き換える必要はないため、一部を省略化できる。例えば、ジャンボジェットのような旅客機をモデリングするとする。胴体、主翼、尾翼、エンジン、車輪、客席などを部品化できる。トイレという部品が不要なら省略する。プラモデルを想像すればよい。
5 UMLでプログラムを設計すること
現実世界のモデリング結果を図示するために、UML(Unified Modeling Language、統一モデリング言語)という表記方法がよく使われる。かつて存在した様々な表記方法を統一することでUMLが考案されたため、事実上UMLが表記方法の世界標準となっている。ここから、モデリングはオブジェクト指向プログラミングのための設計だと言える。
UMLでは、9種類の図(ダイアグラム)が規定されている(下参照)。図の種類が多いのは、現実世界を様々な視点でモデリングした結果を表すためである。例えば、ユーズケース図は、ユーザーの視点(プログラムの使われ方)でモデリングした結果を図示するものである。クラス図などはプログラマの視点である。
- ユースケース図(use case diagram):プログラムの使われ方を示す
- クラス図(class diagram):クラス及び複数クラスの関連を示す
- オブジェクト図(object diagram):オブジェクトを示す
- シーケンス図(sequence diagram):複数オブジェクトの関連を時間に注目して示す
- コラボレーション図(collaboration diagram):複数オブジェクトの関連を協調関係に注目して示す
- ステートチャート図(statechart diagram):オブジェクトの状態変化を示す
- アクティビティ図(activity diagram):処理の流れなどを示す
- コンポーネント図(component diagram):ファイルおよび複数ファイルの関連を示す
- デプロイメント図(deployment diagram):コンピュータやプログラムの配置方法を示す
図1.ユースケース図
図2.クラス図
UMLはモデリングの表記方法を規定しているだけであり、オブジェクト指向プログラミング専用というわけではない。会社の組織図や業務フローなどをUMLで表記することもできる。
オブジェクト指向プログラミングのための設計では、バラバラになった関数と変数を後からクラスにグループ化するのではない。最初に必要な数だけクラスを決め、後から個々のクラスが持つべき関数と変数を列挙していく。すなわち、プログラムの対象となる現実世界を見て「どのような物(クラス)から構成されているのか」と考えるのである。
6 オブジェクト間のメッセージ・パッシングでプログラムが動作するもの
メッセージ・パッシングとは、オブジェクトの持つ関数を呼び出すことである。オブジェクト指向言語でプログラムを作成すると、オブジェクトが他のオブジェクトの持つ関数を呼び出すことでプログラムが動作していく。
オブジェクト指向言語でない場合、プログラムの動作を「フローチャート(流れ図)」で表す(手続き型言語とも言う)。反面、オブジェクト指向言語では、プログラムの動作をUMLの「シーケンス図」や「コラボレーション図」で表す。
図3.シーケンス図
図4.コラボレーション図
7 継承、カプセル化、多態性を使うこと
「継承」「カプセル化」「多態性」は、オブジェクト指向プログラミングの3本柱と呼ばれている。継承(inheritance)とは、既存のクラスの持つメンバーを引き継いで新たなクラスを作成することである。カプセル化(encapsulation)とは、クラスの持つメンバーの中で、クラスの利用者に見せる必要のないものを隠すことである。多態性(polymorphism、多様性や多義性)とは、同じメッセージに対してオブジェクトが複数の操作を行うことである。
既存のクラスを継承すれば、新たなクラスを効率的に作成できる。1つのクラスが複数のクラスに継承されているなら、継承元のクラスを修正するだけで、継承先のすべてのクラスを修正したことになる。カプセル化によって不要なメンバーを隠せば、クラスがブラックボックス化された使いやすい部品となり、保守も容易になる。隠したメンバーは外から使われないので自由に修正できるからである。多態性を利用して、同じメッセージで複数の操作が行えるクラスを作れば、クラスを使う人は覚えることが少なくて済む。結局、どれもオブジェクト指向プログラミングのメリットである開発効率と保守性の向上を実現するものなのである。
クラスとオブジェクトの違い
オブジェクト指向プログラミングでは、クラスとオブジェクトを異なるものとして区別する。クラスはオブジェクトの定義であり、クラスが実体を持ったものがオブジェクト(クラスのインスタンス)である。このことを「クラスはクッキーの型であり、くり抜かれたものがオブジェクトである」と説明している解説書がよくある。メモリー上にクラスのコピー(オブジェクト)を作成してから使うのである。
オブジェクトを作成してから使う理由は、現実世界でもクラス(定義)とオブジェクト(実体)が区別されているからである。例えば企業の従業員を表すJugyoinクラスを定義したとする。定義しただけですぐにJugyoinクラスのメンバーが使えたら、プログラムの中には従業員が1人しか存在できなくなってしまう。Jugyoinクラスのオブジェクトを作成する決まりなら、必要な人数だけ従業員を作る(メモリー上にJugyoinクラスのコピーを作成する)ことができるのである。
クラスの使い方は3通り
クラスの使い方は以下の3つがあり、対象となるクラスの性質とプログラムの目的によって必然的に決まる。
- クラスが持つメンバー(関数と変数)を個別に利用するだけの方法
- クラスの定義の中に他のクラスを含めてしまう方法(集約)
- 既存のクラスを継承して新しいクラスを定義する方法
Javaと.NETではOOPの知識が必須となる
Javaと.NETがオブジェクト指向言語である以上、その知識を身につける必要があるだろう。Javaと.NETはフレームワークと呼ばれ、OS(WindowsやLinuxなど)の上に存在し、OSの複雑さを隠すことで開発を効率化するためのプログラムのセットである。フレームワークは、プログラムを安全に実行してくれる「実行エンジン」と、プログラムの部品群である「クラスライブラリ」から構成されている。
Javaでも.NETでもクラスライブラリを利用したオブジェクト指向プログラミングを行うことが必須となる。Javaでは、フレームワークと同じ名前のJavaという言語を使う。.NETでは、C#、Visual Basic .NET、Visual C++ .NET、NetCOBOLなどの.NET対応言語を使う。どの言語もオブジェクト指向言語である。Visual Basic .NETとNetCOBOLは、従来のVisual BasicとCOBOLにオブジェクト指向プログラミングの機能(クラスの定義、継承、カプセル化、多態性など)を追加したものである。
最後に
オブジェクト指向プログラミングとは「開発効率と保守性の向上を実現する」という目的を果たすために、様々な工夫を行っている言語であることを述べた。
著者の矢沢氏が強調しているように、オブジェクト指向プログラミングは「学問」ではない。プログラマはエンジニアである。エンジニアリングは、学問ではなく経済活動である。あくまで効率的で保守が容易なプログラミング手法として、「実践」することが大切である。
次回は、データベースについてまとめる。
![]() |
Smalltalkを知ってるとOOが物(Object)中心ってのは違和感がありますね。
下記のページなんかが詳しいですが。Smalltalkからの視点から見るとMessageが中心であとは全てオマケに見えます。
例えば下記は、SmalltalkによるsizeというMessageをmessageという変数に保存して、’文字列’という定数Objectに投げつける例です。
| message |
“引き数がある場合は、引き数もmessageに取り込まれる”
message := ( MessageCatcher new ) size.
“‘文字列’にsizeを送信”
message sendTo: ‘文字列’.
この機構を「メッセージ転送」といいます。Smalltalkでは手順(Method)とMessage、型(Class)は独立しており、Messageは単なる関数呼び出しの比喩ではなく実在する機構なのです。ちなみにMessageと「手順」は独立しているため実行時にObjectから削除したり追加したりする事もできます。
小細工的な機構の話は置いといて、重要なのは「手順」や「型」からMessageが独立しているという話です。SmalltalkはMessageの送信手順を記述する事で処理を作成していく言語です。Smalltalkで記述する手順の中には確かにObjectも登場しますが、定数系のObjectを除いてObjectがその正体を見せる(どの「型」に所属しているか、どんな「手順」をもっているか)事は多くありません。屁理屈の域ですがこんな感じでObjectの正体は隠されます。
|myName|
myName := Type name. “Type型が見えているがmyNameの正体は一応不明”
SmalltalkにとってObjectは、Messageの送信先でさえあればよくそれ以上はどうでも良いのです。
前述しましたがSmalltalkはMessageで処理を記述していきます。処理の9割はMessageのやりとりで構成されます。Smalltalkは「手順」という形でこのやりとりを記録し保存します。この「手順」は、「手順」の中にObjectの正体に関する詳細が含まれていなければ無いほど再利用可能になります。逆に「手順」の中にObjectの詳細が含まれていればいる程再利用性がなくなります。
Smalltalkが評価されていたObject指向とは、Objectの詳細を排除し、Messageの集合体である「手順」を再利用しているという所なのです。GoF本なんかは、その考え方がよく現れているいい例でしょう(というかSmalltalkのやり方をパクってるだけにも見えますが)。GoFの本以外にも、RUbyやPythonにも直接的、間接的にその影響が現れています。
まとめると、Smalltak的に考えればOOで重要なのは
「Objectの詳細を排して「手続き(Messageのやり取り)」を再利用すること」
そう感じるが故に、私としてはOOの要点がObjectという言い方には違和感を覚えますね。
ちなみにMessage中心の考えに興味がお有りでしたら、こちらの内容も面白いと思います。
>オブジェクト指向プログラミングは間違いだったか?
>www.infoq.com/jp/news/2010/07/objects-smalltalk-erlang