検索
(2006/08/19)
オブジェクト指向の基本要素は、最もいわれているもので次の3つです。
これからオブジェクト指向について深く追求していく身にとっては少々漠然としています。 iooではオブジェクト指向を理解するポイントとなる点をもう少し整理し紹介します。 個々の内容については別ページにて詳しく説明します。
オブジェクト指向の基本要素である、カプセル化,継承,多態性。この3点はみごと端的に特徴を言い当てています。
感覚的に言えばマクロ的な見方でのポイントです。(否定しているのではないですよー)
ここにiooがミクロ的な見方でのポイントを追加します。
| OO3大要素 | iooOO7大要素 (iooによるOO7大要素) |
|---|---|
| クラス | |
| クラスとインスタンス | |
| カプセル化 | カプセル化 |
| 継承 | クラスの継承 |
| オブジェクトの代入互換性 | |
| 仮想メソッドとオーバーライド | |
| 多態性 (ポリモーフィズム) |
多態性 (ポリモーフィズム) |
要素が倍以上になってしまいましたが、ご安心下さい。要素というと大げさですが、要はポイントは7つということです。 それでは、iooOO7大要素ついて紹介します。
最も基本的で重要な概念です。オブジェクト指向では全てを「もの」として扱うその器(定義)となります。
車を例に考えます。
車は走る・曲がる・止まるなどの動作をしますし、好みの色・形がありますね。
これらをまとめて定義するとこのようになります。(UMLという記述方法のクラス図です)
このように、対象とするものの定義をクラスといいます。 オブジェクト指向ではシステムを全てをクラスで定義します。
実際のものや、事象などからクラスを導き出す能力はとても大切です。
先にクラスを説明しましたが、クラスは定義です。
実際のものからいろいろな情報を抜き出し定義したものがクラスであるのに対して、インスタンスは実体、まさに「もの」のことをいいます。
同じ車の定義である1つの車クラスから複数の車インスタンスを作り出すことができます。 クラスが設計書、インスタンスがそこから作り上げた実際の物となります。
同じ「車」だけど、違う「もの」
オブジェクト指向では、このインスタンス(オブジェクト)の集合でシステムを構築します。 オブジェクト同士のやり取りで表現していく「視点」が必要です。
クラス,インスタンス,オブジェクトの呼び方、使い方に関してはかなりアバウトで、注意が必要です。
同じ意味でこのインスタンスのことを「オブジェクト」とも呼びます。どちらも同じ内容ですが、インスタンスはより「クラスという定義に対しての実体であるモノ」という意味あいが強い呼び方です。
また日常ではそこまで厳密に考えず、「オブジェクト」のことも「クラス」と言ったりもします。
(いちいちそこまで意識せずクラス、クラスということが多いものです)
なので、「クラス」と聞いたらそれが本当に「クラス」なのか、それとも「インスタンス」のことを言っているのかを
区別できるようにならないといけません。
ハードウェアでは「クラスは雛型、インスタンスは実体」でOKですが、間違いではありませんが、 ここで対象にしているのはソフトウェアです。概要はこれでよいですが、やはりソフト的な感覚が必要となりますので実際は少々難しい(おもしろい)かもしれません。 クラスとインスタンスの項目で詳しく説明します。
カプセル化とは、正確には「クラスのカプセル化」です。 カプセル化はクラスを構成する上で非常に大切な項目です。 しかしこのカプセル化のやらんとしていることは特に目新しいことでも難しいことでもありません。 一言でいうと「外部インターフェースは必要最小限にしましょう」となります。 構造化プログラミング的にいうと「スコープをできるだけ小さくね」です。
例えばエレベーターをクラスとして考えた場合、外から行うことのできる操作は限られています。
エレベーターのモーターの回転数を直接調整する事はできないですし、できたらとっても危険ですね。
もう1つ、自動販売機をクラスとして考えた場合、商品の金額以上のお金を入れないと商品を購入できる状態(ボタンのランプが付く)になりません。
消費者がこの状態に直接することはできないですし、できたら商品だけ持っていかれます。(きっと・・)
このようにクラスという枠組みを、中は触れない、しっかり守られている1つのカプセルのようなイメージでいい例えています。 自身の処理やデータの保持などは自分の中で行い外部からは触れないようしっかりとカプセルで覆います。 外部に許す操作やデータ参照は最小限に抑えて公開するようにします。
※ハードウェアなど身の回りの実際の物では普通に行われていることです
カプセル化についてはこちらをご覧ください
クラスの継承とは、
既にあるクラスに定義されている内容をそのまま引き継いで新しいクラスを定義すること
です。新しいクラスには新たにメソッドの追加・上書きなど拡張をすることができます。
次のようなクラスを例にあげます。
ClassAは歩くことのできるクラスです。このクラスを継承してClassBを定義して、新たにrunを追加しています。
定義上ClassBにはwalkの定義はありませんが、ClassAの定義を全て引き継ぐので、特に定義をしていなくてもwalkする(歩く)ことができます。
このようにクラスは継承をして新たに機能を追加することができます。
継承はオブジェクト指向によって実現できる新しい要素です。 この継承により、以降に示すような楽しい要素が登場してきます。
ただ継承はむやみに使うと後で自分の首を締めることになりかねません。 同じ処理があるからといって、それだけで上位のクラスを作るといったことは止めた方がいいです。(継承は慎重に・・・
これはあまりクローズアップされない、陰の重要なポイントです。
少々プログラム的に考えないと難しい(というかプログラムを通して考えたほうがわかり易い)ですが、ここを言葉だけでなく真からイメージできたら「カプセル化」を除くiooOO7大要素を全てクリアできていると言ってもいいというくらい要(かなめ)です。
「オブジェクトの代入互換性」
ですが、正確に言い換えると
「クラスのインスタンス(オブジェクト)への参照値は、そのクラスの上位のクラス型変数に型変換することなく代入することができる」
となります。(「オブジェクト指向」という概念に対する説明とすると御幣があるかもしれませんが、少なくとも「オブジェクト指向言語を使ってオブジェクト指向を説明する」とすると間違えではありません)
簡単なプログラムで例をあげます。ここにParentクラスと、これを継承したChildクラスがあるとします。
そして次のような事が可能です。
1|Parent parent = new Child(); 2|parent.Say();
だからどうした?というような2行ですが、内容は次の通りです。
ちなみに下の2つはNGです。
1|Child child = new Parent(); // ×代入できません
1|Parent parent = new Child(); 2|parent.Smile(); // ×ParantクラスにはSmile処理は存在しないので呼べません
この上位への代入ができるおかげで、Parent型変数のparentが参照しているインスタンスは、ParentクラスのインスタンスかもしれないしChildクラスのインスタンスかもしれない。 これができてこそオブジェクト指向独特の世界が生まれているのです。
詳細は別途記述します。
継承にて新しいクラスを作成した際、次のように同名のメソッドの定義を行うことができます。
この時、SaruクラスのCryメソッドはAnimalクラスのCryメソッドをオーバーライドしたメソッド、
AnimalクラスのCryメソッドは、仮想メソッドとなります。
少々プログラム的に考察する必要がありますが、JAVAは全てのメソッドがこのように、仮想メソッドかオーバーライドしたメソッドです。
C++, C#, VB.NET, Delphiなどは、継承したクラスで同名のメソッドが定義できないメソッドがデフォルトとなっており、
仮想メソッド,オーバーライドは明記的に記述する必要があります。
ここでは、オブジェクト指向独特の現象は、仮想メソッドとメソッドのオーバーライドがあってこそだということだけ意識しておいてください。 詳細は別途記述します。
「上位クラスへの代入互換性」と「仮想メソッドとオーバーライド」から導かれる動作がこの多態性です。 1つのオブジェクトに対する同じ命令で、多くの状態(動作)を取り得ることをそう呼んでいます。
例をあげると、 人間に「立て」というと、ビシッと立ち上がる人もいれば、めんどくさそうに立つ人もいる。もしかしたら無視して立たない人もいるかもしれません。 同じ人間に同じように「立て」と言っているのに、人により動作が異なる。このような事を多態性と言っています。
簡単なプログラム例を1つ。
1|Animal animal = null; 2| 3|Buta buta = new Buta(); 4|Saru saru = new Saru(); 5|Uma uma = new Uma(); 6| 7|animal = buta; 8|animal.Cry(); 9| 10|animal = saru; 11|animal.Cry(); 12| 13|animal = uma; 14|animal.Cry();
8,11,14行目で、animalに鳴けと言っていますが、それぞれの命令でどうなるかというと、
となります。
先ほどの人間の例と同じですね。
この動作を利用することで、似た性質を持つ異なるオブジェクトを統一して処理することが出来るようになります。
フレームワークを構成する際には必須の事象です。フレームワークに限らず部品などでも非常に有効です。