Rubyを使ってオブジェクトの概念を説明していく。
オブジェクトはなにかを厳密に説明するのはむずかしい。
ここではオライリー出版の「初めてのRuby」(著Yugui)からの定義を借りると、
オブジェクトとは、
1.アイデンティティを持っている
2.メッセージを受け取る
3.内部状態を持つ
オブジェクトとは自分が何者か知っていて、名前を持ち、メッセージを受け取ってなんらかの処理を施す、内部状態を持つとは、例えば,
Integerは大きさをもつ、Stringは長さをもち、Arrayは格納する箱を持つ具合に、、、
"aa".object_id #固有のオブジェクトのIDを持つ
=> 70243805533380
"aa".length #Stringクラスに所属する「 "aa" 」は長さという状態を持ち、メッセージを受け取って処理をする。
=> 2
また オブジェクトとはクラスの参照とインスタンス変数 を持っている。
クラスの参照とはオブジェクトの所属するクラスの事である。
1.class
=> Fixnum
[1,2,5].class
=> Array
全てのオブジェクトはなんらかのクラスに所属し、仲良くやっている。
メソッドが呼ばれるとオブジェクトはクラスの問い合わせを行い自分の所属するクラスにメソッドがあるか探索する。
よく勘違いされるのがオブジェクト自身がメソッドを持つという事
###オブジェクト自身はメソッドは持っていない!
例えば「"aaa"」オブジェクトがあるとし文字列の長さが知りたい。
"aaa".length
=> 3
文字列が3と返ってくる。これは内部でオブジェクトがクラスへ問い合わせをし、そのクラスのインスタンスメソッドを探すのだ。
あるクラスに所属するメソッドをインスタンスメソッドといい、このメソッドは?と言う時は後で後述するがクラスメソッドの事をさしているかもしれないし、特異メソッドの事を指しているかもしれない。このインスタンスメソッドメソッドはと言う時とは、ニュアンスが違うので少し注意が必要である。だけどこれは慣れの問題かもしれない。
"aaa".class.instance_methods(false)
# 引数にfalseを指定したのは継承したクラスのインスタンスメソッドやmixinしたインスタンスメソッドを取り除くため(後で後述)
=> [:<=>, :==, :===, :eql?, :hash, :casecmp, :+, :*, :%, :[], :[]=, :insert, :length, :size, :bytesize, :empty?, :=~, :match, :succ, :succ!, :next, :next!, :upto, :index, :rindex, :replace, :clear, :chr, :getbyte, :setbyte, :byteslice, :scrub, :scrub!, :freeze, :to_i, :to_f, :to_s, :to_str, :inspect, :dump, :upcase, :downcase, :capitalize, :swapcase, :upcase,,,省略]
ちなみに"aaa".lengthと書いた時にメッセージを受け取る側のオブジェクトを レシーバ と呼んだりする。
Rubyは組み込みクラスといって始めからクラスが取り込まれているものがあって、簡単な表記でオブジェクトが作れるようになっている。
これを リテラル といい、例えば、
1
=> 1
1.class
=> Fixnum
"aa"
=> "aa"
"aa".class
=> String
というような感じで簡単にオブジェクトを生み出す事ができる。
本来であればクラスを作り、そこからオブジェクトを生み出さなくちゃいけない。
class Cat
def nyaaa
puts "nyaaa"
end
def tuna_kan
puts "Nyaaaa~!!!"
end
end
a = Cat.new
a.object_id
=> (なんらかの数字の列)
レシーバにクラス名を指定してnewメソッドを呼び出すとオブジェクトが作れる。
ちなみにレシーバにクラス名を指定して呼び出すメソッドを クラスメソッド という。
クラス名は 定数 と言って最初の一文字以上は大文字で始めなきゃいけない決まりがある。
オブジェクトの作成方法はは三種類ある、リテラル表記を使った簡潔なものか、変数に格納したものか、クラス名で指定したもの。オブジェクトはクラスメソッドの「new」を使って作り出すと書いたが、クラス自身もオブジェクトになることができ、全てのクラスはClassクラスのインスタンスになっている。
ここでインスタンスという言葉を使った。
インスタンス とはあるクラスに所属するオブジェクトという事
例、
a = Cat.new # => Catクラスのインスタンス
"aaa" # => Stringクラスのインスタンス
123 # => Fixnumクラスのインスタンス
[1,2,3] # => Arrayクラスのインスタンス
{aaa: 122} # => Hashクラスのインスタンス
:aaa # => Simbolクラスのインスタンス
ではこれらのクラスたちはなんのインスタンスなのか???
Cat.class
=> Class
String.class
=> Class
Fixnum.class
=> Class
Array.class
=> Class
Hash.class
=> Class
Simbol.class
=> Class
つまり、全てのクラスはClassクラスのオブジェクトに所属する!!!
a = "aaa".class
=> String
a.class #あるいは "aaa".class.class
=> Class
下記の図を見ながら、そういうものだと理解する。
###すべてのクラスはClassクラスのインスタンス!と呪文のように唱えて覚える。
またオブジェクトはインスタンス変数を持っている。
以下の例を参照
class Nisikasai
def cat
@cat = "cat"
end
end
a = Nisikasai.new
a.cat
=> "cat"
a.instance_variables
=> [:@cat]
インスタンス変数は値を代入した時に初めて出現する、オブジェクトごとに異なる値を持つ。
##まとめ
###オブジェクトのメソッドはオブジェクトが参照されるクラスのインスタンスに移住していて、インスタンス変数はオブジェクト自身に移住している。