オブジェクト指向とは何か考える
概要
OOPとは何か、もちろんオブジェクト指向のことなのはわかる。
しかしオブジェクト指向について、3年間プログラミングをやってきたが自信を持って分かると断言出来ない。
なので今回はそのオブジェクト指向とは何なのかをゼロから考える。
考える際の材料は基本的にWikipediaから見つけていくが、OOP関連の記事はそれなりに洗礼されていると思うので大した問題では無い。
Wikipediaさんの言葉
オブジェクト同士の相互作用として、システムの振る舞いをとらえる考え方である。 ※ Wikipedia より引用 システムの振る舞いのとらえ方について述べている。
まずオブジェクト同士の相互作用というのが直感的ではない、ここがOOPの難しい点の一つだと思う。
手続き型の考えが簡単なのは、システムの振る舞いを直感的にとらえる考え方だから。
その為、プログラミング初心者はOOPの言語を触っても手続き型で書いてしまう。
そもそもオブジェクトとは何なのか、相互作用とはどういうことなのかを深掘りしたほうが良さそうだ。
オブジェクトとは
早速抽象化という言葉が出てきた、OOPでは良く抽象化という言葉を目にする気がする。
オブジェクトが抽象化するのは処理ではなく「手続きの対象」らしい。
つまり、動作では無くなんらかの物 ( 実体があるとは限らない ) であるということが分かる。
この辺はある程度理解しているつもりなのでもう少し読み進める。
関連するデータを束ね、代入、演算、手続き(関数やメソッドなど)を介した受け渡しといった操作の対象にでき、またメッセージの受け手になれる実体をオブジェクトと呼ぶ ※ Wikipedia より引用 幾つか要素が出てきたので整理する。
関連するデータを束ねる ( メンバ変数のこと? )
代入、演算が出来る ( インスタンスの格納や演算子オーバロードのこと? )
メソッドを介した受け渡し ( 引数でインスタンスを渡せること? )
メッセージの受け手になれる実体
今度出てきたのはメッセージという単語、これも何なのか調べる。
メッセージとは
オブジェクト間の通信と聞くとなんとなく分かるが、コードではどう表現されるのだろうか。
もう少し読み進めると答えが書いてあった。
多くのプログラミング言語においてメッセージは、メソッド呼び出しの比喩でしかないことが多い。 ※ Wikipedia より引用 なるほど、メソッドの呼び出しがメッセージということになるのか。
つまりクラスAとクラスBがある時、クラスAがクラスBのメソッドを呼び出すということは
「クラスAがクラスBにメッセージを送った」という意味になるということなのだろう。
しかしこれは全ての言語に対して当てはまる物ではなく、言語によってはメッセージ送信用の機構を独立して持っている物もあるらしい。(SmalltalkやObjective-C)
一つ前の項目に出てきた「メッセージの受け手になれる実体」というのはメソッドを外から呼び出せるクラスという意味だと受け取って良さそうだ。
相互作用とは
相互作用はWikipediaに詳細な説明は無いが、自分では理解出来た。
まず「オブジェクト同士の相互作用として、システムの振る舞いをとらえる考え方である。」についてだが恐らくこう。
オブジェクトが他のオブジェクトのメソッドを呼び出して内部状態を変える
この繰り返しでシステムの振る舞いを表現する
ここでクソみたいな例えをすると分かりづらい入門書のようになってしまうが、構わず簡易的な扇風機で例える。
スイッチを押したら羽が回るという単純な物だ。
ここで出て来るオブジェクトは下記の4つだ。
人 (Human)
スイッチ (Switch)
羽 (feather)
人は扇風機をONにするメソッド (pushSwitch) を持つ。
スイッチはON/OFFを切り替えるメソッド (toggleSwitch) 持つ。
羽もスイッチと同じメソッドに加え、自身の状態として羽が回っているかどうか (isRotation) を持つ。
コードで書くと下記のようになる。
code:Fan.java
// 人
class Human {
void pushSwitch() {
Switch switch = new Switch();
switch.toggleSwitch();
}
}
// スイッチ
class Switch {
void toggleSwitch() {
Feather feather = new Feather();
feather.toggleSwitch();
}
}
// 羽
class Feather {
private boolean isRotation = false;
void toggleSwitch() {
this.toggleIsRotation();
}
private void toggleIsRotation() {
this.isRotation = !this.isRotation;
}
}
// エントリポイント
public class Main() {
public static void main(String[] args) {
Human human = new Human();
human.pushSwitch();
}
}
人がスイッチを押すと扇風機の羽が回る。
相互作用を視覚化するにはUMLのシーケンス図が見やすいので書いてみた。
https://gyazo.com/0a00015d9eab5c5086b5ecd8d8532dd4
だいぶ相互作用感が見えてきた。
これは扇風機を押して羽を回すまでの手順だが、その実装はオブジェクトがメッセージを送ることで実現されている。
エントリポイントで人が創造され、その人はスイッチを押しているだけだが結果としては羽が回る。
これこそが「オブジェクト同士の相互作用として、システムの振る舞いをとらえる考え方である。」ということだろう。
まとめ
大事なのはシステムの捉え方、ここを間違えるとOOPにはならない。
OOPの三大要素とかあるが、これはそれ以前の問題だと思う。
(それ以前の問題を疎かにしてOOPで苦戦する人は多いと感じる)
ぐだぐだな記事になってしまったがメモなのでセーフ。
今日はこれで一旦区切る、また今度深掘りして視野を広げつつまとめる。