はじめに
個人的にオブジェクト指向を理解するのに苦戦しまくったので、その真髄を世界一分かりやすく説明していきます。
何か間違いなどあればどんどんご教示お願いします。言語はRubyです。
対象読者
- Ruby、Railsを勉強中の方
- 業務でRubyを使っている方
- チェリー本やRailsチュートリアルで挫折しちゃった人
オブジェクト指向とは
オブジェクト指向とは、プログラムを「手順」ではなく、「モノの作成と反応」として見る考え方です。これだけではイマイチ分からないと思うので、具体的なコードを使って説明していきます。
オブジェクト指向を理解するには、手続き型のコードを知るのが早いです。
例えば、ある数字を加工して、その数字を使って文章を作って、結果を出力するとき、手続き型では以下のように書きます。
def calculate(number_1, number_2)
number_1 * number_2 + 1
end
def update_content(value)
"結果は#{value}です"
end
def output(content)
puts content
end
value = 100
content = ""
new_value = calculate(value,20)
// 2001
content = update_content(new_value)
// "結果は2001です"
output(content)
=> "結果は2001です"
一方で、オブジェクト指向で書くとこんな感じ。
num = Num.new(100,"")
num.calculate(20)
// 2001
num.update_content
// "結果は2001です"
num.output
=> "結果は2001です"
なんとなく違いは分かりますか?
前者は、先に関数を定義して、処理を実行するたびにいろんなメソッドに値を飛ばして、返ってきた値を変数に代入して...
と流れるようにプログラムが進んでいきます。
なんだか忙しそうですよね?
一方で後者は、はじめにnum
というモノを作成し、そいつに対して「計算して」「中身を更新して」「出力して」と呼びかけるような感じで処理が進んでいきます。
情報の記憶も処理の内容も「モノ」が全部やってくれるので、一度作ってしまえば見通しよく実行できるわけです。
この後者こそがまさに、オブジェクト指向の考え方であり、今回でいう所のnum
がオブジェクトと呼ばれるものです。
つまり、オブジェクト指向とは、__コードにオブジェクトという主人公を登場させ、それをメインに話を進めていく設計の考え方__といえます。
やっぱり、ドラマを見るにも、主人公がいた方が面白いし分かりやすいじゃないですか。
プログラミングも同じで、処理の中に主人公がいた方が読みやすくて扱いやすくなるわけです。
ちなみにnumというオブジェクトは以下のクラスから作成されていました。へぇ〜ぐらいで流してください。
class Num
attr_accessor :value, :content
def initialize(value, content)
@value = value
@content = content
end
def calculate(number)
self.value = value * number + 1
end
def update_content
self.content = "計算結果は#{value}です"
end
def output
puts content
end
end
num = Num.new(100,"")
num.calculate(100)
num.update_content
num.output
オブジェクトとは
先ほどの例で少しはオブジェクト指向の雰囲気を掴めたかと思います。
では、オブジェクトとは一体なんでしょうか?
こいつの正体を掴むのに僕は半年ほどかかりました。そして、僕が腑に落ちた例えで分かりやすーーーく説明します。
結論から言うと、オブジェクトとは魔法の箱です。
この魔法の箱は2つの性質を持ちます。
- 情報を持つ
- 反応する
プログラミングをやっていると、オブジェクトが色んなことをしているように見えますが、結局やっていることはこの2つだけなんです。
情報を保持するから「箱」、メッセージに対して反応できるから「魔法の」と言う例えにしました。
オブジェクトとは、情報を持ち、メッセージに対して反応するただの箱なんだ。
とりあえず今の段階ではそのように理解してもらえれば大丈夫です。
1. 情報を持つとは?
オブジェクトは情報を持つことができます。分かりやすいのが以下の例。
user.name
=> 山田
user.age
=> 18
これは__user__という魔法の箱がname
とage
という2つの情報を持っていることを示しています。すごく簡単ですね。
この情報はいつでも呼び出すことができますし、その気になれば更新することも消すこともできます。
2. 反応するとは?
オブジェクトはあるメッセージに対して__反応する__こともできます。
user.hello
=> "おはようございます。"
これまで5万回は見たhelloの例です。
これは、hello
というメッセージを伝えたら"おはようございます。"
と返すようにuser
という魔法の箱が__反応した__と見ることができます。
userを__レシーバ__、helloを__メッセージ__と呼ぶのはこのような理由です。
ちなみに、そこらへんのゴミ箱にhelloと話しかけても何も返事しません。
dustbox.hello
=> NameError (undefined local variable or method `dustbox' for main:Object)
userという箱が反応してくれたのは、事前に反応パターンを記憶させたからです。
class User
def hello
puts "おはようございます。"
end
end
このように、魔法の箱(オブジェクト)に教え込む反応方法のことを__メソッド__と言います。
では、この教えこむ場所のことを(学校の)クラスと呼ベばかなり分かりやすいのではないかと閃きました。
言い換えれば、classとは魔法の箱の養成クラスとでもいいましょうか。
すごく簡単にまとめると...
- オブジェクトとは魔法の箱である
- 魔法の箱は、情報を持ったり、メッセージに対して反応したりできる
- 魔法の箱に教え込む反応パターンのことをメソッドと呼ぶ
- 反応パターンを教え込む場所のことをクラスと呼ぶ
- オブジェクト指向とは、プログラムを「手順」ではなく、「魔法の箱(オブジェクト)の反応」と見る考え方
以上が、オブジェクト指向の説明になります。
この記事でオブジェクト指向への理解が少しでも深まれば幸いです。
追記1
Numクラスのソースコードに間違いがあったため、修正いたしました。
ご指定いただいた方々ありがとうございます。
変更点
-
Class Num => class Num
へ修正 - 属性名を
num => value
へ変更。(属性名とインスタンス名が同じだとややこしいため) - caluculateメソッドにおける、
value = => self.value
に修正(属性を上書きする際はself.の省略はできないようです。)