なんでこんな記事を書こうと思ったか自分でも謎であるが、自分の理解したことをアウトプットするために書いてみたいと思う。
てなわけで間違いは勘弁してください。
オブジェクト指向を説明しようとすると、どうしても概念的であったり抽象度が高くなってしまうのでなるべく現実に沿って説明したつもりです。
一般的なオブジェクト指向の説明
オブジェクト指向とは、コンピュータプログラムの設計や実装についての考え方の一つで、互いに密接に関連するデータと手続き(処理手順)をオブジェクト(object)と呼ばれる一つのまとまりとして定義し、様々なオブジェクトを組み合わせて関連性や相互作用を記述していくことによりシステム全体を構築していく手法。
引用元
「オブジェクト指向」という言葉は概念的な物だと思っているので本や人によって言ってることが違うことが起こりやすい。
概念的な話をダラダラとしていても理解がしにくいので
概念→具体例のトップダウンじゃなくて
具体例→概念のボトムアップでオブジェクト指向に出てくる色々な用語から説明してみたいと思う。
オブジェクト指向における用語を車好きの為に。
カプセル化
オブジェクト指向を勉強しようと思ったら絶対に出てくる言葉です。
突然ですが車を運転するためにはどんな事が必要でしょう?
無免許運転でも運転は出来るので免許取るとかは置いといて。
- エンジン始動
- ギア操作(AT・MTに限らず)
- アクセル踏む
- ブレーキ踏む
- ハンドル操作
ぐらいが思いついたのでは無いのでしょうか?
でも、車の内部ではもっと複雑な事が起こっているのは車好きなら知っていると思います。
エンジン始動っていうだけで人間の操作は鍵を回すか最近はプッシュ式ですが、内部では
- バッテリーから電源を供給
- 燃料ポンプ
- スタータリレー
- セルモーター
- プラグコード
- プラグで火花飛ばす
等など色々過程があった上で初めてエンジンが始動できます。
もちろん上記は一例です。ECUが介入してNポジションじゃないと始動できないとか色々ありますが、本来は複雑な操作があって初めてエンジンが始動できるということが伝えたいことです。
そんな複雑な操作を鍵を回すかボタンを押すかのめちゃくちゃ簡単な操作でエンジン始動出来るようにしてくれているのがカプセル化の仕組みです。(厳密に言うとデータ操作が〜とか一元化が〜とかになるので省略)
言い換えると、運転手は車の内部構造を把握せずともエンジンを始動できるのです!!
更に利点はあります。「運転手が内部構造を把握せず」と書いていますが、正確に言えば運転手は内部構造を把握できないようになっています。
なぜそんなことするかって??
簡単です、運転手(素人)に下手に内部を弄られて壊されたくないからです。ド素人が点火タイミングとか弄りはじめたらエンジンが壊れるのと一緒です。
車のメンテナンスをする人からしたら下手に壊される心配が無いのです。
なので敢えて内部構造は見せないほうが都合が良いのです。
更にまだまだ利点は続きます。
思い立って車の給排気系の見直しでマフラーを変えたとしましょう。ついでにパワーアップがしたかったのでタービンも変えました。プラグコードもいいやつに......
ってこんな感じで内部構造が変わったとしても運転手がエンジンを始動するために必要なのは鍵を回すかボタンを押すかです。
つまり、内部構造が変わってもエンジン始動の手続きは変わらないのです。
何当たり前のこと言ってんだ?みたいな目で見られそうですけど、プログラミングする上ではすごく大事です。
ちょっと難しい話ですが、突然変更があっても呼び出す側は呼び出す方法さえ知っていればいいのですから。
カプセル化まとめ
-
内部構造を把握せずともエンジンが始動できる
-
内部構造を見せないことで素人に壊されることを防ぐ
-
内部構造が変わってもいつもの手続きでエンジン始動ができる
継承(インヘリタンス)
さて、話は変わってあなたは車の開発者であるとしましょう。
話は逸れますが「車」ってそもそも概念的な物だと思いませんか?
車って言ってもSUVタイプであったりクーペであったりオープンカーであったり様々あります。
また、SUVっていってもフォレスターだったりCX5だったり色々な車種があります。
一言に車を開発しようと思っても色々な種類があるのが分かります。
バスみたいな大きい車を開発するのと、セダン型の車を開発するのでは全然違います。
でも「車」が持っている基本的な物や機能いうのはどのタイプの車でも一緒だと思いませんか?
物としては
- バッテリー
- タイヤ
- エンジン
- ブレーキ
機能としては
- アクセルで走る
- ブレーキで止まる
- ハンドルで曲がる
があると思います。これらのようなどんな車にも共通している機能をまとめた物を親クラスであったり抽象クラスであると思って下さい。
でもこれらは抽象的なものに過ぎないので、このままでは車には乗れません。
ここから具体化して車を設計していく必要があります。
これらの「車」という概念がもっている物や機能をひな形として、これを元にバスであったりSUVを開発していきます。
実際にバスを開発するとしましょう。
車の持っている基本的な物として「車の概念」から引っ張ってきます。(バッテリーetc)
これだけでは概念であるので実際に設計します。
バスならば大容量なバッテリーが必要だし、大きいタイヤ、大きいエンジンが必要です。
- バッテリー(5時間率容量で96Ahを直列でつないで24V)
- タイヤ(275/70R22.5)
- エンジン(12000cc)
- ブレーキ(凄いやつ)
というふうに概念であったものを実際に具体的に実装します。
更にバスにはSUVにはない機能が必要です。
例えば
- トイレ
- 電光掲示板
等など必要になってきます。
これがSUVだと
- 優れた4WDシステム
とか追加が必要です。
つまり「車」という概念の雛形を作っておいて、実際にバスを作ろうと思ったら
「車」の概念の機能+バス特有の機能
SUVタイプを作ろうと思ったら
「車」の概念の機能+SUV特有の機能
と「車」の概念にある機能を引き継いだ上で様々な機能を付け足す上で実際の車を設計していきます。
ここでは「車」とバス・SUVの間に親子関係が出来ています。
親(ここでは「車」)の持っている機能というのは子(バス・SUV)も持っていて、更に子(バス・SUV)は独自の機能を追加して他の子と差別化します。
「車」という概念の雛形を作ることで、バスタイプにしろSUVタイプ・クーペタイプを設計するときでも最小限の機能追加で車が出来上がるので労力が少なくて済むわけです。
これをもっと効率よく設計したいなーとなった時には
「車」の雛形→セダンの雛形→クラウンやマークX
と雛形から雛形を作ることによってセダンを開発するときにはもっと楽に開発することが出来ます。
実際の開発ではこのあたりのどのくらいまで抽象するかってのを決めたり、どの切り口から抽象化するかが大事になったりします。
例えば
-
乗り物→陸上の乗り物→タイヤで動くもの→車→セダン→トヨタ→クラウン
-
エンジンが付いているもの→レシプロ型エンジン付き→4つのタイヤがある→セダン→トヨタ→クラウン
と最終的にはクラウンにたどり着くけれど切り口が違うかったりします。
抽象度にしても、乗り物という概念は必要か?など考える必要があります。
クラウンを作ったとしてもまだまだ細かく分けてハイブリッド車と分けることだって可能です。
どこまで細かくするか?どこまで大きくするかって考えるの大事です。
PS
オブジェクト指向詳しい人なら、抽象クラスと色々と混ざったりしていると感じるかもしれませんが勘弁してください。
継承(インヘリタンス)まとめ
- 雛形を作っておき、その機能を引き継いだ上で新たなものを作るとこで効率がいい
- (後述しますが)多態性を実現することが可能になる
多態性・多様性・ポリモーフィズム
多態性・多様性・ポリモーフィズム(以下ポリモーフィズムで統一)は継承と密接な関係があったりします。
次はあなたは車の運転手だとしましょう。
「車」の概念の機能として
- アクセルで走る
- ブレーキで止まる
- ハンドルで曲がる
があるとします。(継承で説明したのと同じです。)
さて、今から凄いこと書きます。
上手に運転できるかは置いといて、トラックだろうがバスだろうが、SUVだろうがセダンだろうが
エンジンさえ掛かっていれば貴方はどんな車でも動かす事ができます。
何が凄いかって言うと、トラックみたいな大きい車でもV6車でもV8車でもハイブリッド車でも
「アクセルを踏めば走る」という事さえ知っていれば貴方は車を動かすことが出来るのです。
ハイブリッドの用に最初はモータで動くみたいな複雑な内部構造でも、「アクセルを踏めば走る」って知っているだけで動かすことが出来るのです。
ただし前提条件として、「車」の概念の機能を継承して作られたものだけに限ります。
逆に言うと、「車」の概念を継承して作られたものは全て「アクセルを踏めば走る」という機能が実装されているので、継承されていればどんな車でも動かすことができます。
ブレーキにしても同じです。
「車」の概念を継承して作られた車は全てブレーキ踏めば止まることが分かっているので、バスだろうがトラックだろうがブレーキの仕組みを知らなくてもブレーキペダルを踏むだけで車を止める事ができます。
このように、実際どのような構造しているかの内部構造を知らなくとも、「アクセルで走る・ブレーキで止まる」という機能さえ知っていればいいのです。
余談ですが、こんな冗談があったりします。
Q:電球を取りつけるのに何人のイギリス人(Englishmen) が必要ですか?
A1:0人。連中ならむしろ闇を呪ってる方がまし。
A2:1人。彼が紅茶を飲んでいる間に外国人の召使いが取り替える。
といった冗談にならって
Q:電球を取りつけるのに何人のオブジェクト指向プログラマー が必要ですか?
A: 0人。単に電球に自分自身を変えるように指示するだけでよいので。
というオブジェクト指向を分かる人ならちょっとクスッと来るような冗談があります。
多態性・多様性・ポリモーフィズムまとめ
- 内部構造を知らなくとも、機能さえ知っていればどんな車でも操作できる。
オブジェクト指向はどう役に立つのか?
車というのはオブジェクトが組み合わさって出来たものです。
ここでいうオブジェクトというのは、バッテリーであったりタイヤであったりマフラーであったり、ありとあらゆるパーツだと思ってください。
車好きな人なら一度はマフラーを変えたことがあると思います。(偏見)
ネジやガスケットの工程はありますが、要はマフラーを引っこ抜いて新しいマフラーつけるだけです。
これができるのはオブジェクト指向のおかげなのです。
マフラーというオブジェクトは
- エンジンから来た排気ガスを受け入れる
- 消音する
- 外に出す
という機能を持っています。
エンジン始動に大きく関わったり、ブレーキ操作に関わることはないです。
マフラーという存在がこのような機能に特化しているからこそ部品を交換するだけでいいのです。
バッテリーという電気を放電したり充電するだけの機能に特化。
これらの特化したパーツを組み上げる事で車を作っています。
他のパーツと密接な関係を持っていたり、1つのパーツに複雑な機能を何個も搭載していたら簡単に交換は出来ません。
更にパーツが1つの機能に特化していると、不具合があっても簡単に治すことが出来ます。
車を組み立てるときも、パーツを使いまわしたりも出来たりします。
車種が違うのにエンジンが共通しているとか、ブレーキが一緒とか、そういうことです。
これだけ書けば明確な利点を書いていなくても車好きの方なら沢山の利点を理解してくれるはずです。
最後に
オブジェクト指向というのは奥が深いです。
クラスとかインスタンスの説明も省略しているので、オブジェクト指向の取っ掛かりぐらいだと思っておいてください。
オブジェクト指向を説明しようとすると、どうしても概念的であったり抽象度が高くなってしまうのでなるべく現実に沿って説明したつもりです。(2回目)
気が向けば他の用語も車を使って説明したいと思います。
あと表記ゆれは気にしないでください。