At line 9 changed 8 lines |
正解は「データ構造が異なる」です。\\ |
クラスの根本は、構造体(データ構造)とそれを扱う処理(関数orメソッド)を一体化させたものです。 |
次のリンクはSunのJava入門のページですが、そこにある図を参照して下さい。 |
[What Is an Object?|http://download.oracle.com/javase/tutorial/java/concepts/object.html]\\ |
Fieldsというのが構造体のことで、その周りをMethods(処理)が取り巻いています。この図は、クラスを基に生成されたオブジェクトの概念を書いたものですが、オブジェクトの設計図となるクラスの定義も同様な考え方です。\\ |
この図からも解るように、データ構造を持たないクラスはそもそもクラスとして機能しません。クラスの原理に反するからです。\\ |
ですが、データ構造を持たないクラスをJavaなどの言語では定義出来てしまうため、単なる関数を定義しただけのclassをクラスと勘違いしている設計者/プログラマーが大勢います。 |
public staticなメソッドのみのクラスがそれです。ユーティリティクラスとも呼ばれます。 |
正解は「__3.データ構造が異なる__」です。\\ |
クラスの根本は、 |
*データ構造(構造体)とそれを扱う処理(関数orメソッド)を一体化させたもの |
です。\\ |
データ構造というのは属性(プロパティ)の集まりのことで、それら属性の値を読んだり編集したりするために処理は存在します。\\ |
\\ |
次の図はOracleのJava入門のページに書いてあるものです。出典: [What Is an Object?|http://download.oracle.com/javase/tutorial/java/concepts/object.html]\\ |
At line 18 changed 4 lines |
!!責務がクラスを決めるのではないのか? |
クラスは「責務」によって定義されるといくつかの解説書には書いてありますが、これは誤りだと私は考えています。誤りが言い過ぎだとしても、初学者に大きな誤解を少なくとも与えています。\\ |
責務という言葉を言い換えると「しなければならないこと」「出来なければならないこと」となります。クラスを利用する側から見るとそのクラスが何を出来るか(してくれるか)は確かに重要です。\\ |
ですがそれは使う側から見た場合であって、設計する人はそれだけではクラスを定義出来ません。一つ例を出します。\\ |
[{Image src='http://download.oracle.com/javase/tutorial/figures/java/concepts-object.gif'}] |
Fieldsというのがデータ構造のことで、その周りを処理(Methods)が取り巻いています。この図は、クラスを基に生成されたオブジェクトの概念を書いたものですが、オブジェクトの設計図となるクラスの定義も同様な考え方です。\\ |
この図からも解るように、 |
*データ構造を持たないクラスはそもそもクラスとして機能しない |
のです。データ構造と処理の一体化というクラスの原理に反するからです。\\ |
At line 23 changed 15 lines |
!!「ジュース売り」という責務 |
「ジュース売り」という責務を考えてみます。\\ |
ジュース売りがしなければならないことは次のような事です。 |
#注文を聞く |
#金額を伝える |
#お金をもらう |
#品物とお釣りを渡す |
では、この責務を請け負えるモノは何が考えられるでしょうか?\\ |
!!ジュース売りを請け負えるモノとは? |
*人間 |
*自動販売機 |
ジュース売りを請け負えるモノとして少なくともこの2つが考えられます。将来的には「ロボット」も入ってくるかもしれません。\\ |
つまり責務が決まったからと言ってそのモノまでは決められないのです。\\ |
これは当然で、「何が出来るのか」というのは処理の規定であって、データ構造、つまりそのモノの状態は関係無いからです。\\ |
Javaなどでは「Interface」として定義するのが責務です。Interfaceはメソッドを規定するだけで中身は実装者任せです。まさに、「責務は決めるがモノは決めない」という機能です。ちなみに私はInterfaceのことを責務ではなく「役割」と呼ぶようにしています。 |
!!クラスの成り立ち |
手続き型の時代から、オブジェクト指向のクラスがどのようにして生まれたのかを見ていきます。\\ |
{{{手続き型の言語においても共通するデータ構造(構造体)を最初に決めます。}}} |
[class_history01.png] |
{{{次に処理(関数)を作成し、処理と処理がデータ構造を受け渡す形で |
ロジックを組み立てます。}}} |
[class_history02.png] |
{{{ところが似たような処理があちこちに意図せず作成されてしまいます。}}} |
[class_history03.png] |
{{{これを避けるために処理を共通化して共通関数を作成し、共通関数のみを |
利用するような開発ルールを設けます。しかし仕組みとしての強制力がないため、 |
似たような関数が複数生まれる危険性は変わりません。}}} |
[class_history04.png] |
{{{この危険性を取り除いたのがオブジェクト指向でのクラスです。データ構造が |
共通関数を持つように仕組みとして強要します。}}} |
[class_history05.png] |
At line 39 changed 5 lines |
!!みんななぜ間違うのか? |
世間ではクラスと思われているものが実は誤りである。なぜそうなってしまうのでしょうか?\\ |
クラスを設計する際、その基となるのは顧客からの要求です。要件と呼ばれます。この要件は、「xxxがしたい」「mmmが出来るようになりたい」という実務処理の記述です。言ってしまえば役割を列挙したものです。\\ |
役割というのは上で書いたように処理に過ぎません。クラスとして必要なデータ構造はそれだけでは出て来ません。\\ |
そのため、オブジェクト指向に不慣れな設計者・実装者はその要件(処理)だけを頼りに開発してしまいます。データ構造を考えずに処理だけを追いかけてしまうのです。これが誤りの根本です。 |
!!クラスの中核はデータ構造 |
上記で見たように、クラスの最初に必要なのは |
*共通化されたデータ構造 |
です。\\ |
共通関数というものを開発したことのある人は解ると思いますが、 |
*関数(処理)を共通化するためには受け渡されるパラメータをまず共通化する |
必要があります。パラメータが複数ある場合、それらをひとかたまりにまとめるとデータ構造(構造体)になります。\\ |
つまり手続き型の言語においても、 |
*処理を共通化する前にデータ構造を共通化 |
していたのです。クラスにおいては、 |
*共通化されたデータ構造が処理も持てる |
ようになっています。 |
*そのクラスを基にした個体(インスタンスあるいはオブジェクト)をメモリ上に複数生成 |
出来ます。これがオブジェクト指向の原理です。 |
At line 47 changed one line |
*役割(責務)をクラスにしてはいけない |
|
!!コラム |
「クラスとはデータ構造のこと」と社内の若手プログラマー達に教えています。\\ |
正確に言うと「データ構造と処理を一体化したもの」なんですが、クラスを見分ける際に最初にやることはデータ構造を考えることなので上記のように繰り返し言っています。 |
にもかかわらず彼らは処理に目が行ってしまい、手続き型の考えにすぐなってしまいます。\\ |
これが人間の本能なのかは判りませんが、プログラマーはそれに陥りやすいと思って設計者は設計する必要があるようです。 |
つまり曖昧な言葉による表現は避け、きちんとしたクラス図を書いて依頼し、プログラマー任せの製造は避けるべきだと考えています。\\ |
またプログラマー達がコードのみで考える状態から脱却するため、早いうちからクラス図の読み書きを修得するよう指導することも重要です。\\ |
\\ |
次: [責務はクラスではない] |