Fujitsu The Possibilities are Infinite

 

オブジェクト指向プログラミングへの道
2日目:オブジェクト指向のプログラム


知史

知史さん

航祐

航祐君

そして、次の日…。 新人の航祐(こうすけ)君とそのチューターの知史(さとし)さんの会話です。

昨日はオブジェクト指向言語について復習しました。 今日はプログラムの作成です。


航祐

「知史先輩、こんにちは」


知史

「やあ、航祐君か。 さっそく昨日の問題をやってみよう」

先輩の知史さんは、解説を加えながらスラスラとプログラムとクラス図を書きました。


(Userクラス)
図解: Userクラス

まず、契約者の名前や料金プランを管理するUserクラスを作ります。 ただし、料金プランの処理はUserクラスでは直接扱わず、その処理を行うPlanクラスを取り込んでそこにまかせます。 実際には上記リストの(1)のようにplanを宣言して、(2)のようにPlanクラスの処理を呼びます。

このようなやり方はオブジェクト指向では良く使うので名前が付いています。 (1)のようにあるクラスの中に別のクラスのオブジェクトを取り込むことを「オブジェクトコンポジション」といい、(2)のように取り込んだクラスに処理をまかせることを「委譲(delegation:デリゲーション)」といいいます。 オブジェクトコンポジションはまたhas-a関係と言われることもあります。

将来、集金処理(未収金があるかなど)などの機能を追加するときも、Userクラスがもとになります。 すなわち、Userクラスはユーザ情報の管理の基地として考え、個々の細かい処理はそれぞれのクラスに委譲するのです。

このとき、各処理に固有のデータは各クラスで独自に管理します。 例えばPlanクラスであれば契約形態、集金処理クラスであれば支払い状況などのデータなどを管理します。 このように処理とその処理に使うデータをまとめて扱うことを、オブジェクト指向では「カプセル化」と呼んでいます。 これもオブジェクト指向プログラミングでは最も重要な考え方の1つです。

さて、次にPlanクラスを見てみましょう。 このクラスはUserクラスから呼ばれて基本料金などの契約情報を基に料金計算を行います。 契約情報の設定はPlanクラスを継承したサブクラスで行います。

(Planクラス)
図解: Planクラス

では、そのサブクラスである、楽々プランクラスと得々プランクラスを見てみましょう。 通常はサブクラスに処理(メソッド)を書きますが、この例では料金計算処理は共通なので、処理(chargeメソッド)はスーパークラスであるPlanクラスに書き、サブクラスではそれぞれの契約情報を設定しているだけです。

(楽々プランクラス)-Planクラスを継承している
図解: 楽々プランクラス

(得々プランクラス)-Planクラスを継承している
図解: 得々プランクラス

最後に、これらを呼ぶメインプログラムを書きます。

(メインプログラム)
図解: メインプログラム

オブジェクト指向で書いたプログラムは以上で終わりです。 クラスの関係がちょっと複雑なので図に書いてみましょう。 以下の図はUMLのクラス図の規則にしたがって書いたものです。

(クラス図)
図解: クラス図



航祐

「うわ~複雑ですね」


知史

「そうだね。 プログラムコードは20行から50行と倍以上になった。 しかし、これによって拡張性は、ぐっと増したのだ。 昨日まとめた拡張性の要件がどのように実現されるか見てみよう」

「要件は次の通りだったね」

  1. 着信中心のユーザや、ヘビーユーザ用の新プランの開設
  2. 通信相手や時間帯による通話料の相違など料金計算ロジックの多様化
  3. メールサービスや集金処理などまったく別の業務処理への拡張

航祐

「まず1番目の要件です。 新プランへの対応はPlanクラスを継承したサブクラスを1つずつ作ることで可能です。 もとの課題では楽々プランクラスと得々プランクラスだけでしたが、同様なプランをいくらでも増やせます。 プランを増やすにはそのクラスを追加するだけで、他のクラスは全く変更が不要です」


知史

「そうだ。 実際にプログラムを書いて見るとオブジェクト指向のメリットがよく判るだろう。 今、航祐君が言ったように他のクラスを全く変更せずに追加できることが、独立性ということだ。 このようにカプセル化と継承によって独立性が実現できるのだ」


航祐

「次は2番目の要件ですが、このままでは料金計算のロジックを変えると、Planクラスのchargeメソッドに手が入ってしまいます」


知史

「そうなんだよ。 ここは少し悩ましい問題があるんだ。 Java言語のインターフェースの機能を使うとスマートに解決できるんだが、少し複雑になるので、この問題はまた別の機会に廻すことにして次に行こう」


航祐

「はい。 楽しみにしています。 3番目の要件は問題ありません。 例えば集金処理や、メールの料金計算を追加するなら、それぞれを管理するクラスを作り、Userクラスに取り込むことで、他の処理とは独立したプログラムとすることができます」


知史

「そうだね。 航祐君にもオブジェクト指向のありがたさが判ったのではないかな」


航祐

「はい。 オブジェクト指向を使うとプログラムの拡張性が増します。 規模が大きくなっても、プログラムの見通しが損なわれません」


知史

「そうだ。 それにプログラムの再利用も可能になる。 しかしオブジェクト指向は良いところばかりではない。 まずこの例で見たようにサイズが大きくなる。 構造も複雑だ。 また作るのも決して簡単ではない」


航祐

「そうですね。 実例があったので、これらの利点と欠点が具体的な形でよく判りました」


知史

「良かったね。 最後にオブジェクト指向言語の誤解をまとめておこう」

◎オブジェクト指向言語の誤解

  • オブジェクト指向言語を使うと、再利用ができる。
  • オブジェクト指向言語を使うと、機能変更に強い。
  • オブジェクト指向言語を使うと、生産性が高まる。

◎これらはすべて正しくない。 正しくは以下の通り。

  • オブジェクト指向言語を使うと、再利用可能な設計ができる。
  • オブジェクト指向言語を使うと、機能変更に強い設計ができる。
  • オブジェクト指向言語を使うと、短期的には工数はむしろ増える。
    →再利用や機能変更容易性による削減が可能。